Hvordan komme filtype fra strengen i C ++

stemmer
70

Gitt en streng filename.conf, hvordan jeg bekrefte utvidelsen delen?

Jeg trenger en kryssplattformløsning.

Publisert på 09/09/2008 klokken 13:57
kilden bruker
På andre språk...                            


24 svar

stemmer
129

Er dette for enkelt for en løsning?

#include <iostream>
#include <string>

int main()
{
  std::string fn = "filename.conf";
  if(fn.substr(fn.find_last_of(".") + 1) == "conf") {
    std::cout << "Yes..." << std::endl;
  } else {
    std::cout << "No..." << std::endl;
  }
}
Svarte 09/09/2008 kl. 14:23
kilden bruker

stemmer
42

Den beste måten er å ikke skrive kode som gjør det, men kaller eksisterende metoder. I vinduene, PathFindExtension er metoden trolig den enkleste.

Så hvorfor skulle du ikke skrive din egen?

Vel, ta strrchr eksempel, hva skjer når du bruker denne metoden på følgende string "c: \ programfiler \ AppleGate.Net \ readme"? Er "Net \ readme" utvidelsen? Det er lett å skrive noe som fungerer for noen eksempel tilfeller, men kan være mye vanskeligere å skrive noe som fungerer for alle tilfeller.

Svarte 09/09/2008 kl. 14:20
kilden bruker

stemmer
32

Du må sørge for at du tar vare på filnavn med mer enn en prikk. Eksempel: c:\.directoryname\file.name.with.too.many.dots.extville ikke håndteres riktig av strchrellerfind.

Min favoritt ville være boost filsystem bibliotek som har en forlengelse (bane) -funksjonen

Svarte 09/09/2008 kl. 14:27
kilden bruker

stemmer
28

Forutsatt at du har tilgang til STL:

std::string filename("filename.conf");
std::string::size_type idx;

idx = filename.rfind('.');

if(idx != std::string::npos)
{
    std::string extension = filename.substr(idx+1);
}
else
{
    // No extension found
}

Edit: Dette er en cross platform løsning siden du ikke nevner plattformen. Hvis du er spesifikt på Windows, vil du ønsker å utnytte Windows-spesifikke funksjoner som er nevnt av andre i tråden.

Svarte 09/09/2008 kl. 14:20
kilden bruker

stemmer
22

Noen andre nevnte løft, men jeg ville bare legge til selve koden for å gjøre dette:

#include <boost/filesystem.hpp>
using std::string;
string texture         = foo->GetTextureFilename();
string file_extension  = boost::filesystem::extension(texture);
cout << "attempting load texture named " << texture
     << "    whose extensions seems to be " 
     << file_extension << endl;
// Use JPEG or PNG loader function, or report invalid extension
Svarte 09/10/2012 kl. 02:46
kilden bruker

stemmer
17

faktisk STL kan gjøre dette uten mye kode, anbefaler jeg deg å lære litt om STL fordi det lar deg gjøre noen fancy ting, anyways dette er hva jeg bruker.

std::string GetFileExtension(const std::string& FileName)
{
    if(FileName.find_last_of(".") != std::string::npos)
        return FileName.substr(FileName.find_last_of(".")+1);
    return "";
}

denne løsningen vil alltid returnere utvidelsen selv på strenger som "this.abcdesmp3" hvis det ikke finner utvidelsen vil returnere "".

Svarte 22/12/2010 kl. 03:30
kilden bruker

stemmer
8

Egentlig er den enkleste måten

char* ext;
ext = strrchr(filename,'.') 

En ting å huske på: Hvis '.'ikke eksisterer i filnavnet, vil ext være NULL.

Svarte 30/07/2013 kl. 10:26
kilden bruker

stemmer
5

Jeg har snublet inn på dette spørsmålet i dag selv, selv om jeg allerede hadde en fungerende kode jeg fant ut at det ikke ville fungere i noen tilfeller.

Mens noen mennesker allerede foreslått å bruke noen eksterne biblioteker, jeg foretrekker å skrive min egen kode for læringsformål.

Noen svar inkludert den metoden jeg brukte i første omgang (på jakt etter den siste " '), men jeg husket at på linux skjulte filer / mapper starter med'.". Så hvis filen filen er skjult og har ingen forlengelse, ville hele filnavnet bli tatt for forlengelse. For å unngå at jeg skrev denne delen av koden:

bool getFileExtension(const char * dir_separator, const std::string & file, std::string & ext)
{
    std::size_t ext_pos = file.rfind(".");
    std::size_t dir_pos = file.rfind(dir_separator);

    if(ext_pos>dir_pos+1)
    {
        ext.append(file.begin()+ext_pos,file.end());
        return true;
    }

    return false;
}

Jeg har ikke testet dette fullt ut, men jeg tror at det skal fungere.

Svarte 17/11/2012 kl. 11:26
kilden bruker

stemmer
4
_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w

Jeg tror dette er Windows (Platform SDK) bare?

Svarte 09/09/2008 kl. 14:03
kilden bruker

stemmer
3

Gode ​​svar, men jeg ser de fleste av dem har noen problemer: Først av alt tror jeg et godt svar bør arbeide for å få fullstendige filnavn som har sine bane overskrifter, også det skal fungere for Linux eller Windows, eller som nevnt det skal være kryss-plattform. For de fleste av svarene; filnavn uten forlengelse, men en bane med et mappenavn inkludert prikk, vil funksjonen ikke returnerer riktig filtype: eksempler på noen test tilfeller kan være som følger:

    const char filename1 = {"C:\\init.d\\doc"}; // => No extention
    const char filename2 = {"..\\doc"}; //relative path name => No extention
    const char filename3 = {""}; //emputy file name => No extention
    const char filename4 = {"testing"}; //only single name => No extention
    const char filename5 = {"tested/k.doc"}; // normal file name => doc
    const char filename6 = {".."}; // parent folder => No extention
    const char filename7 = {"/"}; // linux root => No extention
    const char filename8 = {"/bin/test.d.config/lx.wize.str"}; // ordinary path! => str

" Brian Newman " forslag vil mislykkes for filnavn1 og filename4. og de fleste andre svar som er basert på omvendt funn vil mislykkes for filnavn1. Jeg foreslår blant annet følgende metode i kilde: som er funksjonen returnerer indeksen for første tegnet for forlengelse eller lengden på gitte strengen hvis ikke funnet.

size_t find_ext_idx(const char* fileName)
{
    size_t len = strlen(fileName);
    size_t idx = len-1;
    for(size_t i = 0; *(fileName+i); i++) {
        if (*(fileName+i) == '.') {
            idx = i;
        } else if (*(fileName + i) == '/' || *(fileName + i) == '\\') {
            idx = len - 1;
        }
    }
    return idx+1;
}

du kan bruke koden ovenfor i c ++ program som følger:

std::string get_file_ext(const char* fileName)
{
    return std::string(fileName).substr(find_ext_idx(fileName));
}

Det siste punktet i noen tilfeller en mappe er gitt til fil navn som argument, og inkluderer en prikk i mappenavnet funksjonen vil returnere mappe dot etterfølgende så bedre første til brukeren kontrollere at det angitte navnet er et filnavn og ikke mappenavn.

Svarte 08/11/2014 kl. 22:49
kilden bruker

stemmer
3

En NET / CLI-versjon du bruker System :: String

   System::String^ GetFileExtension(System::String^ FileName)
   {
       int Ext=FileName->LastIndexOf('.');
       if( Ext != -1 )
           return FileName->Substring(Ext+1);
       return "";
   }
Svarte 25/07/2011 kl. 20:05
kilden bruker

stemmer
3

For røye array-type strenger kan du bruke denne:

#include <ctype.h>
#include <string.h>

int main()
{
    char filename[] = "apples.bmp";
    char extension[] = ".jpeg";

    if(compare_extension(filename, extension) == true)
    {
        // .....
    } else {
        // .....
    }

    return 0;
}

bool compare_extension(char *filename, char *extension)
{
    /* Sanity checks */

    if(filename == NULL || extension == NULL)
        return false;

    if(strlen(filename) == 0 || strlen(extension) == 0)
        return false;

    if(strchr(filename, '.') == NULL || strchr(extension, '.') == NULL)
        return false;

    /* Iterate backwards through respective strings and compare each char one at a time */

    for(int i = 0; i < strlen(filename); i++)
    {
        if(tolower(filename[strlen(filename) - i - 1]) == tolower(extension[strlen(extension) - i - 1]))
        {
            if(i == strlen(extension) - 1)
                return true;
        } else
            break;
    }

    return false;
}

Kan håndtere filbaner i tillegg til filnavn. Fungerer med både C og C ++. Og på tvers av plattformer.

Svarte 23/01/2011 kl. 23:49
kilden bruker

stemmer
3

Ved hjelp av std :: string finne / rfind løser dette problemet, men hvis du jobber mye med stier så bør du se på boost :: filsystem :: vei siden det vil gjøre koden mye renere enn å fikle med rå streng indekser / iteratorer.

Jeg foreslår boost siden det er en høy kvalitet, godt testet, (open source og kommersielt) fri og bærbar bibliotek.

Svarte 13/12/2009 kl. 21:34
kilden bruker

stemmer
2

Jeg bruker disse to funksjonene for å få forlengelse og filnavn uten forlengelse :

std::string fileExtension(std::string file){

    std::size_t found = file.find_last_of(".");
    return file.substr(found+1);

}

std::string fileNameWithoutExtension(std::string file){

    std::size_t found = file.find_last_of(".");
    return file.substr(0,found);    
}

Og disse regextilnærmingene for visse ekstra krav:

std::string fileExtension(std::string file){

    std::regex re(".*[^\\.]+\\.([^\\.]+$)");
    std::smatch result;
    if(std::regex_match(file,result,re))return result[1];
    else return "";

}

std::string fileNameWithoutExtension(std::string file){

    std::regex re("(.*[^\\.]+)\\.[^\\.]+$");
    std::smatch result;
    if(std::regex_match(file,result,re))return result[1];
    else return file;

}

Ekstra krav som er oppfylt av regex metoden:

  1. Hvis filnavnet er som .configeller noe sånt som dette, utvidelsen vil være en tom streng og filnavn uten forlengelse vil være .config.
  2. Hvis filnavnet ikke har noen forlengelse, vil forlengelse være en tom streng, filnavn uten utvidelse blir filnavnet uendret.

REDIGERE:

De ekstra krav kan også bli møtt av følgende:

std::string fileExtension(const std::string& file){
    std::string::size_type pos=file.find_last_of('.');
    if(pos!=std::string::npos&&pos!=0)return file.substr(pos+1);
    else return "";
}


std::string fileNameWithoutExtension(const std::string& file){
    std::string::size_type pos=file.find_last_of('.');
    if(pos!=std::string::npos&&pos!=0)return file.substr(0,pos);
    else return file;
}

Merk:

Slippe gjennom kun de filnavn (ikke sti) i de ovennevnte funksjoner.

Svarte 19/08/2015 kl. 20:03
kilden bruker

stemmer
2

Jeg vil gå med boost::filesystem::extension, men hvis du ikke kan bruke Boost og du må bare bekrefte forlengelse, er en enkel løsning:

bool ends_with(const std::string &filename, const std::string &ext)
{
  return ext.length() <= filename.length() &&
         std::equal(ext.rbegin(), ext.rend(), filename.rbegin());
}

if (ends_with(filename, ".conf"))
{ /* ... */ }
Svarte 02/05/2015 kl. 17:14
kilden bruker

stemmer
1

Med C ++ 17 og dens std::filesystem::path::extension(biblioteket er etterfølgeren til å øke :: filsystem) du vil gjøre din uttalelse mer uttrykksfulle enn å bruke f.eks std::string.

#include <iostream>
#include <filesystem> // C++17
namespace fs = std::filesystem;

int main()
{
    fs::path filePath = "my/path/to/myFile.conf";
    if (filePath.extension() == ".conf") // Heed the dot.
    {
        std::cout << filePath.stem() << " is a valid type."; // Output: "myFile is a valid type."
    }
    else
    {
        std::cout << filePath.filename() << " is an invalid type."; // Output: e.g. "myFile.cfg is an invalid type"
    }
}

Se også std :: filsystem :: banen :: stammen , std :: filsystem :: banen :: filnavn .

Svarte 15/06/2018 kl. 19:28
kilden bruker

stemmer
1

Dette er en løsning jeg kom opp med. Deretter la jeg merke til at det er likt det @serengeor postet.

Det fungerer med std::stringog find_last_of, men den grunnleggende ideen vil også fungere hvis modifisert til å bruke chararrays og strrchr. Den håndterer skjulte filer og ekstra prikker som representerer den gjeldende katalogen. Det er plattformuavhengig.

string PathGetExtension( string const & path )
{
  string ext;

  // Find the last dot, if any.
  size_t dotIdx = path.find_last_of( "." );
  if ( dotIdx != string::npos )
  {
    // Find the last directory separator, if any.
    size_t dirSepIdx = path.find_last_of( "/\\" );

    // If the dot is at the beginning of the file name, do not treat it as a file extension.
    // e.g., a hidden file:  ".alpha".
    // This test also incidentally avoids a dot that is really a current directory indicator.
    // e.g.:  "alpha/./bravo"
    if ( dotIdx > dirSepIdx + 1 )
    {
      ext = path.substr( dotIdx );
    }
  }

  return ext;
}

Unit test:

int TestPathGetExtension( void )
{
  int errCount = 0;

  string tests[][2] = 
  {
    { "/alpha/bravo.txt", ".txt" },
    { "/alpha/.bravo", "" },
    { ".alpha", "" },
    { "./alpha.txt", ".txt" },
    { "alpha/./bravo", "" },
    { "alpha/./bravo.txt", ".txt" },
    { "./alpha", "" },
    { "c:\\alpha\\bravo.net\\charlie.txt", ".txt" },
  };

  int n = sizeof( tests ) / sizeof( tests[0] );

  for ( int i = 0; i < n; ++i )
  {
    string ext = PathGetExtension( tests[i][0] );
    if ( ext != tests[i][1] )
    {
      ++errCount;
    }
  }

  return errCount;
}
Svarte 19/08/2015 kl. 21:20
kilden bruker

stemmer
1

Her er en funksjon som tar en sti / filnavn som en streng og returnerer utvidelsen som en streng. Det er alle standard c ++, og skal fungere på tvers av plattformer for de fleste plattformer.

I motsetning til flere andre svar her, håndterer det odde saker som Windows' PathFindExtension håndtak, basert på PathFindExtensions dokumentasjon.

wstring get_file_extension( wstring filename )
{
    size_t last_dot_offset = filename.rfind(L'.');
    // This assumes your directory separators are either \ or /
    size_t last_dirsep_offset = max( filename.rfind(L'\\'), filename.rfind(L'/') );

    // no dot = no extension
    if( last_dot_offset == wstring::npos )
        return L"";

    // directory separator after last dot = extension of directory, not file.
    // for example, given C:\temp.old\file_that_has_no_extension we should return "" not "old"
    if( (last_dirsep_offset != wstring::npos) && (last_dirsep_offset > last_dot_offset) )
        return L"";

    return filename.substr( last_dot_offset + 1 );
}
Svarte 28/04/2014 kl. 16:51
kilden bruker

stemmer
1

Hvis du bruker Qt-biblioteket, kan du gi en prøve å QFileInfo 's suffiks ()

Svarte 02/03/2014 kl. 11:03
kilden bruker

stemmer
1

Eller du kan bruke denne:

    char *ExtractFileExt(char *FileName)
    {
        std::string s = FileName;
        int Len = s.length();
        while(TRUE)
        {
            if(FileName[Len] != '.')
                Len--;
            else
            {
                char *Ext = new char[s.length()-Len+1];
                for(int a=0; a<s.length()-Len; a++)
                    Ext[a] = FileName[s.length()-(s.length()-Len)+a];
                Ext[s.length()-Len] = '\0';
                return Ext;
            }
        }
    }

Denne koden er kryss-plattform

Svarte 07/08/2013 kl. 10:13
kilden bruker

stemmer
1

Prøv å bruke strstr

char* lastSlash;
lastSlash = strstr(filename, ".");
Svarte 11/05/2012 kl. 07:56
kilden bruker

stemmer
0

Jeg brukte PathFindExtension () -funksjonen til å vite om det er en gyldig tif-fil eller ikke.

#include <Shlwapi.h>
bool A2iAWrapperUtility::isValidImageFile(string imageFile)
{
    char * pStrExtension = ::PathFindExtension(imageFile.c_str());

    if (pStrExtension != NULL && strcmp(pStrExtension, ".tif") == 0)
    {
        return true;
    }

    return false;
}
Svarte 20/01/2016 kl. 17:24
kilden bruker

stemmer
0

Hvis du anser utvidelsen som den siste prikken og mulige tegn etter det, men bare hvis de ikke inneholder katalogen skilletegn, returnerer følgende funksjon utvidelsen starter indeksen, eller -1 hvis ingen forlengelse funnet. Når du har som du kan gjøre hva du vil, som stripe forlengelse, endre det, sjekk det etc.

long get_extension_index(string path, char dir_separator = '/') {
    // Look from the end for the first '.',
    // but give up if finding a dir separator char first
    for(long i = path.length() - 1; i >= 0; --i) {
        if(path[i] == '.') {
            return i;
        }
        if(path[i] == dir_separator) {
            return -1;
        }
    }
    return -1;
}
Svarte 17/12/2015 kl. 10:59
kilden bruker

stemmer
0

Hvis du tilfeldigvis bruke Poco bibliotekene kan du gjøre:

#include <Poco/Path.h>

...

std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"
Svarte 16/11/2015 kl. 06:46
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more