Comment obtenir une extension de fichier à partir d’une chaîne en C ++

Étant donné une chaîne "filename.conf" , comment puis-je vérifier la partie extension?

J’ai besoin d’une solution multiplateforme.

    Vous devez vous assurer que vous vous occupez des noms de fichiers avec plus d’un point. exemple: c:\.directoryname\file.name.with.too.many.dots.ext ne serait pas géré correctement par strchr ou find.

    Mon préféré serait la bibliothèque de système de fichiers boost qui a une fonction d’extension (chemin)

    Est-ce trop simple d’une solution?

     #include  #include  int main() { std::ssortingng fn = "filename.conf"; if(fn.substr(fn.find_last_of(".") + 1) == "conf") { std::cout < < "Yes..." << std::endl; } else { std::cout << "No..." << std::endl; } } 

    Le meilleur moyen est de ne pas écrire de code qui le fasse, mais d’appeler des méthodes existantes. Dans Windows, la méthode PathFindExtension est probablement la plus simple.

    Alors pourquoi ne pas écrire les vôtres?

    Eh bien, prenons l’exemple strrchr, que se passe-t-il lorsque vous utilisez cette méthode sur la chaîne suivante “c: \ program files \ AppleGate.Net \ readme”? Est-ce que “.Net \ readme” est l’extension? Il est facile d’écrire quelque chose qui fonctionne pour quelques exemples, mais il peut être beaucoup plus difficile d’écrire quelque chose qui fonctionne dans tous les cas.

    En supposant que vous ayez access à STL:

     std::ssortingng filename("filename.conf"); std::ssortingng::size_type idx; idx = filename.rfind('.'); if(idx != std::ssortingng::npos) { std::ssortingng extension = filename.substr(idx+1); } else { // No extension found } 

    Edit: Ceci est une solution multiplateforme puisque vous n’avez pas mentionné la plateforme. Si vous êtes spécifiquement sous Windows, vous souhaiterez tirer parti des fonctions spécifiques à Windows mentionnées par d’autres utilisateurs du thread.

    Quelqu’un d’autre a mentionné le boost mais je voulais juste append le code pour faire ceci:

     #include  using std::ssortingng; ssortingng texture = foo->GetTextureFilename(); ssortingng 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 

    en fait, la STL peut le faire sans trop de code, je vous conseille d’en apprendre un peu sur la STL car elle vous permet de faire des choses fantaisistes, de toute façon c’est ce que j’utilise.

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

    cette solution retournera toujours l’extension même sur des chaînes comme “this.abcdesmp3” si elle ne trouve pas l’extension, elle retournera “”.

    En fait, le plus simple est

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

    Une chose à retenir: si '.' n’existe pas dans le nom de fichier, ext sera NULL .

    J’ai trébuché sur cette question aujourd’hui même si j’avais déjà un code de travail, j’ai compris que cela ne fonctionnerait pas dans certains cas.

    Alors que certaines personnes ont déjà suggéré d’utiliser certaines bibliothèques externes, je préfère écrire mon propre code à des fins d’apprentissage.

    Certaines réponses incluaient la méthode que j’utilisais en premier lieu (en recherchant le dernier “.”), Mais je me souvenais que sur Linux, les fichiers / dossiers cachés commençaient par “.”. Donc, si le fichier est caché et n’a pas d’extension, le nom complet du fichier sera pris pour extension. Pour éviter cela, j’ai écrit ce morceau de code:

     bool getFileExtension(const char * dir_separator, const std::ssortingng & file, std::ssortingng & 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; } 

    Je n’ai pas testé cela complètement, mais je pense que cela devrait fonctionner.

     _splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w 

    Je pense que c’est Windows (Platform SDK) seulement?

    Utiliser std :: ssortingng’s find / rfind résout ce problème, mais si vous travaillez beaucoup avec les chemins, vous devriez regarder boost :: filesystem :: path car cela rendra votre code beaucoup plus propre que de bidouiller les index / iterators de chaînes brutes.

    Je suggère de booster car c’est une bibliothèque de haute qualité, bien testée, (open source et commercialement) et entièrement portable.

    Pour les chaînes de type tableau, vous pouvez utiliser ceci:

     #include  #include  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 ssortingngs 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; } 

    Peut gérer les chemins de fichiers en plus des noms de fichiers. Fonctionne avec C et C ++. Et multi-plateforme.

    Bonnes réponses, mais je vois que la plupart d’entre eux ont quelques problèmes: Tout d’abord, je pense qu’une bonne réponse devrait fonctionner pour les noms de fichiers complets qui ont leur titre, qui devrait également fonctionner pour Linux ou Windows ou comme mentionné. Pour la plupart des réponses; les noms de fichiers sans extension, mais avec un chemin avec un nom de dossier incluant dot, la fonction ne pourra pas renvoyer l’extension correcte: des exemples de cas de test pourraient être les suivants:

      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 

    La suggestion ” brian newman ” échouera pour nomfichier1 et nomfichier4. et la plupart des autres réponses basées sur la recherche inverse échoueront pour nomfichier1. Je suggère d’inclure la méthode suivante dans votre source: qui est la fonction retournant l’index du premier caractère d’extension ou la longueur de la chaîne donnée si non trouvé.

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

    vous pouvez utiliser le code ci-dessus dans votre application c ++ comme ci-dessous:

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

    Le dernier point dans certains cas, le dossier est atsortingbué au nom du fichier en tant qu’argument et inclut un point dans le nom du dossier. La fonction renverra le point du dossier si bien que l’utilisateur vérifie d’abord que le nom

    Une version NET / CLI utilisant System :: Ssortingng

      System::Ssortingng^ GetFileExtension(System::Ssortingng^ FileName) { int Ext=FileName->LastIndexOf('.'); if( Ext != -1 ) return FileName->Subssortingng(Ext+1); return ""; } 

    J’irais avec boost::filesystem::extension mais si vous ne pouvez pas utiliser Boost et que vous avez juste à vérifier l’extension, une solution simple est:

     bool ends_with(const std::ssortingng &filename, const std::ssortingng &ext) { return ext.length() < = filename.length() && std::equal(ext.rbegin(), ext.rend(), filename.rbegin()); } if (ends_with(filename, ".conf")) { /* ... */ } 

    J’utilise ces deux fonctions pour obtenir l’ extension et le nom de fichier sans extension :

     std::ssortingng fileExtension(std::ssortingng file){ std::size_t found = file.find_last_of("."); return file.substr(found+1); } std::ssortingng fileNameWithoutExtension(std::ssortingng file){ std::size_t found = file.find_last_of("."); return file.substr(0,found); } 

    Et ces approches regex pour certaines exigences supplémentaires:

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

    Besoins supplémentaires satisfaits par la méthode regex:

    1. Si filename est comme .config ou quelque chose comme ça, l’ extension sera une chaîne vide et le nom de fichier sans extension sera .config .
    2. Si nom_fichier n’a aucune extension, l’extension sera une chaîne vide, le nom de fichier sans extension sera le nom de fichier inchangé.

    MODIFIER:

    Les exigences supplémentaires peuvent également être satisfaites par les éléments suivants:

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

    Remarque:

    Ne transmettez que les noms de fichiers (pas le chemin) dans les fonctions ci-dessus.

    Essayez d’utiliser strstr

     char* lastSlash; lastSlash = strstr(filename, "."); 

    Ou vous pouvez utiliser ceci:

      char *ExtractFileExt(char *FileName) { std::ssortingng 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 

    Ce code est multi-plateforme

    Si vous utilisez la bibliothèque Qt, vous pouvez essayer le suffixe QFileInfo ()

    Voici une fonction qui prend un chemin / nom de fichier sous forme de chaîne et renvoie l’extension sous forme de chaîne. Il est tout c ++ standard, et devrait fonctionner multi-plateforme pour la plupart des plates-formes.

    Contrairement à plusieurs autres réponses, il gère les cas particuliers traités par Windows PathFindExtension, en fonction de la documentation de PathFindExtensions.

     wssortingng get_file_extension( wssortingng 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 == wssortingng::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 != wssortingng::npos) && (last_dirsep_offset > last_dot_offset) ) return L""; return filename.substr( last_dot_offset + 1 ); } 

    C’est une solution que j’ai trouvée. Ensuite, j’ai remarqué que c’est similaire à ce que @serengeor a posté.

    Il fonctionne avec std::ssortingng et find_last_of , mais l’idée de base fonctionnera également si elle est modifiée pour utiliser des tableaux de caractères et strrchr . Il gère les fichiers cachés et les points supplémentaires représentant le répertoire en cours. C’est indépendant de la plate-forme.

     ssortingng PathGetExtension( ssortingng const & path ) { ssortingng ext; // Find the last dot, if any. size_t dotIdx = path.find_last_of( "." ); if ( dotIdx != ssortingng::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. // eg, a hidden file: ".alpha". // This test also incidentally avoids a dot that is really a current directory indicator. // eg: "alpha/./bravo" if ( dotIdx > dirSepIdx + 1 ) { ext = path.substr( dotIdx ); } } return ext; } 

    Test de l’unité:

     int TestPathGetExtension( void ) { int errCount = 0; ssortingng 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; } 

    Avec C ++ 17 et son std::filesystem::path::extension (la bibliothèque est le successeur de boost :: filesystem), vous rendrez votre déclaration plus expressive que d’utiliser, par exemple, std::ssortingng .

     #include  #include  // 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: eg "myFile.cfg is an invalid type" } } 

    Voir aussi std :: filesystem :: path :: stem , std :: filesystem :: path :: filename .

    Si vous utilisez des bibliothèques Poco , vous pouvez:

     #include  ... std::ssortingng fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc" 

    Si vous considérez l’extension comme le dernier point et les caractères possibles après cela, mais uniquement s’ils ne contiennent pas le caractère séparateur de répertoire, la fonction suivante renvoie l’index de démarrage de l’extension ou -1 si aucune extension n’a été trouvée. Lorsque vous avez cela, vous pouvez faire ce que vous voulez, comme enlever l’extension, le changer, le vérifier, etc.

     long get_extension_index(ssortingng 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; } 

    J’ai utilisé la fonction PathFindExtension () pour savoir s’il s’agit d’un fichier tif valide ou non.

     #include  bool A2iAWrapperUtility::isValidImageFile(ssortingng imageFile) { char * pStrExtension = ::PathFindExtension(imageFile.c_str()); if (pStrExtension != NULL && strcmp(pStrExtension, ".tif") == 0) { return true; } return false; }