Hoe te bestandsextensie krijgen van string in C ++

stemmen
67

Als een string filename.conf, hoe ik de uitbreiding deel controleren?

Ik heb een cross-platform oplossing.

De vraag is gesteld op 09/09/2008 om 14:57
bron van user
In andere talen...                            


24 antwoorden

stemmen
4
_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w

Ik denk dat dit Windows (Platform SDK) alleen?

antwoordde op 09/09/2008 om 15:03
bron van user

stemmen
26

Ervan uitgaande dat u toegang tot STL hebben:

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: Dit is een cross-platform oplossing, omdat je niet het platform heeft vermeld. Als u specifiek bent op Windows, wil je het Windows-specifieke functies genoemd door anderen in de thread benutten.

antwoordde op 09/09/2008 om 15:20
bron van user

stemmen
39

De beste manier is om niet schrijven een code die het doet maar bel bestaande methoden. In windows, de PathFindExtension methode is waarschijnlijk de meest eenvoudige.

Dus waarom zou je niet je eigen te schrijven?

Nou, neem de strrchr Wat gebeurt er bijvoorbeeld als je deze methode gebruiken voor de volgende string "c: \ program files \ AppleGate.Net \ readme"? Is ".Net \ readme" de uitbreiding? Het is gemakkelijk om iets dat werkt voor een paar bijvoorbeeld gevallen te schrijven, maar kan veel moeilijker zijn om iets dat werkt voor alle gevallen te schrijven.

antwoordde op 09/09/2008 om 15:20
bron van user

stemmen
123

Is dit te eenvoudig van een oplossing?

#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;
  }
}
antwoordde op 09/09/2008 om 15:23
bron van user

stemmen
32

Je moet ervoor zorgen dat u zorg voor bestandsnamen te nemen met meer dan één punt. Bijvoorbeeld: c:\.directoryname\file.name.with.too.many.dots.extzou niet correct worden behandeld door strchroffind.

Mijn favoriet zou zijn boost bestandssysteem bibliotheek dat een verlenging (pad) functie

antwoordde op 09/09/2008 om 15:27
bron van user

stemmen
3

Met behulp van std :: string's find / rfind lost dit probleem, maar als je veel met paden werkt, dan moet je kijken naar boost :: bestandssysteem :: pad omdat het je code veel schoner dan gehannes met ruwe koord indexen / iterators zal maken.

Ik stel voor boost omdat het een hoge kwaliteit, goed getest, (open source en commercieel) gratis en volledig draagbare bibliotheek.

antwoordde op 13/12/2009 om 22:34
bron van user

stemmen
17

daadwerkelijk kan de STL dit te doen zonder al te veel code, raad ik u een beetje over de STL leren omdat het laat je een aantal mooie dingen, anyways dit is wat ik gebruik.

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

deze oplossing zal altijd de extensie terug zelfs op strings als "this.abcdesmp3" als het de extensie zal terugkeren "niet kan vinden".

antwoordde op 22/12/2010 om 04:30
bron van user

stemmen
3

Voor char-array-type strings kun je dit gebruiken:

#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 omgaan met bestandspaden naast bestandsnamen. Werkt met zowel C en C ++. En cross-platform.

antwoordde op 24/01/2011 om 00:49
bron van user

stemmen
3

A NET / CLI-versie met behulp van System :: String

   System::String^ GetFileExtension(System::String^ FileName)
   {
       int Ext=FileName->LastIndexOf('.');
       if( Ext != -1 )
           return FileName->Substring(Ext+1);
       return "";
   }
antwoordde op 25/07/2011 om 21:05
bron van user

stemmen
1

Probeer te gebruiken strstr

char* lastSlash;
lastSlash = strstr(filename, ".");
antwoordde op 11/05/2012 om 08:56
bron van user

stemmen
21

Iemand anders vermeld boost, maar ik wilde alleen maar om de werkelijke code toe te voegen om dit te doen:

#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
antwoordde op 09/10/2012 om 03:46
bron van user

stemmen
5

Ik heb nu zelf op deze vraag struikelde, hoewel ik al een werkende code ik erachter dat het niet zou werken in sommige gevallen gehad.

Terwijl sommige mensen al stelde met behulp van enkele externe bibliotheken, verkies ik mijn eigen code te schrijven voor het leren doeleinden.

Sommige antwoorden waren de methode die ik gebruikte in de eerste plaats (op zoek naar de laatste " '), maar herinnerde ik me dat op linux verborgen bestanden / mappen beginnen met'.". Dus als het bestand bestand is verborgen en heeft geen extensie, zou het hele bestand naam worden genomen voor de uitbreiding. Om te voorkomen dat ik schreef dit stukje code:

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;
}

Ik heb dit niet volledig getest, maar ik denk dat het zou moeten werken.

antwoordde op 17/11/2012 om 12:26
bron van user

stemmen
8

Eigenlijk is de gemakkelijkste manier is

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

Een ding om te onthouden: als '.'niet bestaat in de bestandsnaam, zal ext zijn NULL.

antwoordde op 30/07/2013 om 11:26
bron van user

stemmen
1

Of u kunt dit gebruiken:

    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;
            }
        }
    }

Deze code is platformonafhankelijk

antwoordde op 07/08/2013 om 11:13
bron van user

stemmen
1

Als je Qt bibliotheek te gebruiken, kunt u een keer te proberen te geven QFileInfo 's achtervoegsel ()

antwoordde op 02/03/2014 om 12:03
bron van user

stemmen
1

Hier is een functie die een pad / bestandsnaam neemt als een string en geeft de verlenging als een string. Het is allemaal standaard C ++, en zou moeten werken cross-platform voor de meeste platforms.

In tegenstelling tot een aantal andere antwoorden hier, het zorgt voor de oneven gevallen die windows' PathFindExtension handgrepen, op basis van documentatie PathFindExtensions's.

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 );
}
antwoordde op 28/04/2014 om 17:51
bron van user

stemmen
3

Goede antwoorden, maar ik zie de meeste van hen heeft een aantal problemen: Allereerst denk dat ik een goede antwoord moet voor volledige bestandsnamen die hun titels weg moeten werken, ook het zou moeten werken voor Linux of Windows of zoals gezegd moet het cross-platform zijn. Voor de meeste van de antwoorden; bestandsnamen zonder extensie, maar een pad met een map naam waaronder stip, zal de functie niet het juiste toestel terug te keren: voorbeelden van een aantal testcases zou kunnen zijn als volgt:

    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 " suggestie zal falen voor bestandsnaam1 en filename4. en de meeste andere antwoorden die gebaseerd zijn op omgekeerde vondst zal falen voor bestandsnaam1. Ik stel waaronder de volgende methode in uw bron: die functie met als resultaat index van de eerste teken van uitbreiding of de lengte van de gegeven string indien niet gevonden.

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;
}

kon je de bovenstaande code in uw c ++ applicatie zoals hieronder:

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

Het laatste punt in sommige gevallen de een map wordt gegeven aan bestandsnaam als argument en is voorzien van een punt in de map met de naam van de functie zal terugkeren dot map slepen dus beter eerst naar gebruiker controleren of de opgegeven naam is een bestandsnaam en niet mapnaam.

antwoordde op 08/11/2014 om 22:49
bron van user

stemmen
2

Ik zou gaan met boost::filesystem::extensionmaar als je niet Boost kunt gebruiken en hoef je alleen maar de verlenging te controleren, een eenvoudige oplossing is:

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"))
{ /* ... */ }
antwoordde op 02/05/2015 om 17:14
bron van user

stemmen
2

Ik gebruik deze twee functies om het te krijgen extensie en de bestandsnaam zonder extensie :

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);    
}

En deze regexbenaderingen voor bepaalde extra voorwaarden:

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;

}

Extra eisen die worden voldaan door de reguliere expressie methode:

  1. Als filename is net .configof iets dergelijks, uitbreiding zal een lege string en de bestandsnaam zonder extensie zal zijn .config.
  2. Als filename een verlenging heeft, zal uitbreiding een lege string zijn bestandsnaam zonder extensie zal zijn bestandsnaam ongewijzigd.

BEWERK:

De extra eisen kan ook worden voldaan door de volgende:

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;
}

Notitie:

Pas over de bestandsnamen (niet weg) in de bovengenoemde functies.

antwoordde op 19/08/2015 om 20:03
bron van user

stemmen
1

Dit is een oplossing die ik bedacht. Toen merkte ik dat het is vergelijkbaar met wat @serengeor geplaatst.

Het werkt met std::stringen find_last_of, maar het basisidee zal ook werken als aangepast voor het hanteren chararrays en strrchr. Het behandelt verborgen bestanden, en extra punten die de huidige directory. Het is platform onafhankelijk.

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;
}

Hoofdstuk toets:

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;
}
antwoordde op 19/08/2015 om 21:20
bron van user

stemmen
0

Als je toevallig te gebruiken Poco bibliotheken die u kunt doen:

#include <Poco/Path.h>

...

std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"
antwoordde op 16/11/2015 om 06:46
bron van user

stemmen
0

Als je kijkt naar de uitbreiding als het laatste punt en de mogelijke tekens na het, maar alleen als ze niet mapscheidingsteken bevatten, de volgende functie retourneert de extension starting index, of -1 als er geen verlenging gevonden. Als je dat je kunt doen wat je wilt, zoals strip de uitbreiding, verander het, check it 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;
}
antwoordde op 17/12/2015 om 10:59
bron van user

stemmen
0

Ik gebruikte functie PathFindExtension () om te weten of het een geldig tif-bestand of niet.

#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;
}
antwoordde op 20/01/2016 om 17:24
bron van user

stemmen
1

Met C ++ 17 en haar std::filesystem::path::extension(de bibliotheek is de opvolger van boost :: filesystem) zou u uw verklaring expressiever dan het gebruik van bijvoorbeeld te maken 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"
    }
}

Zie ook std :: bestandssysteem :: pad :: stam , std :: bestandssysteem :: pad :: bestandsnaam .

antwoordde op 15/06/2018 om 19:28
bron van user

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