Comment puis-je extraire le nom de fichier et l’extension d’un chemin d’access en C ++

J’ai une liste de fichiers stockés dans un fichier .log dans cette syntaxe:

 c:\foto\foto2003\shadow.gif D:\etc\mom.jpg 

Je veux extraire le nom et l’extension de ces fichiers. Pouvez-vous donner un exemple d’une façon simple de le faire?

Pour extraire un nom de fichier sans extension, utilisez boost :: filesystem :: path :: stem au lieu de std :: ssortingng :: find_last_of (“.”)

 boost::filesystem::path p("c:/dir/dir/file.ext"); std::cout << "filename and extension : " << p.filename() << std::endl; // file.ext std::cout << "filename only : " << p.stem() << std::endl; // file 

Si vous voulez un moyen sûr (c.-à-d. Portable entre les plates-formes et ne pas mettre de suppositions sur le chemin), je vous recommande d’utiliser boost::filesystem .

Cela ressemblerait en quelque sorte à ceci:

 boost::filesystem::path my_path( filename ); 

Ensuite, vous pouvez extraire différentes données de ce chemin. Voici la documentation de l’object chemin.


BTW: Rappelez-vous aussi que pour utiliser le chemin comme

 c:\foto\foto2003\shadow.gif 

vous devez échapper au littéral chaîne \ :

 const char* filename = "c:\\foto\\foto2003\\shadow.gif"; 

Ou utilisez / place:

 const char* filename = "c:/foto/foto2003/shadow.gif"; 

Cela ne s’applique qu’à la spécification de chaînes littérales dans les guillemets "" , le problème n’existe pas lorsque vous chargez des chemins à partir d’un fichier.

Vous devrez lire vos noms de fichiers à partir du fichier dans std::ssortingng . Vous pouvez utiliser l’opérateur d’extraction de chaîne de std::ostream . Une fois que vous avez votre nom de fichier dans un std::ssortingng , vous pouvez utiliser la méthode std::ssortingng::find_last_of pour trouver le dernier séparateur.

Quelque chose comme ça:

 std::ifstream input("file.log"); while (input) { std::ssortingng path; input >> path; size_t sep = path.find_last_of("\\/"); if (sep != std::ssortingng::npos) path = path.substr(sep + 1, path.size() - sep - 1); size_t dot = path.find_last_of("."); if (dot != std::ssortingng::npos) { std::ssortingng name = path.substr(0, dot); std::ssortingng ext = path.substr(dot, path.size() - dot); } else { std::ssortingng name = path; std::ssortingng ext = ""; } } 

Pour C ++ 17 :

 #include  std::filesystem::path p("c:/dir/dir/file.ext"); std::cout << "filename and extension: " << p.filename() << std::endl; // "file.ext" std::cout << "filename only: " << p.stem() << std::endl; // "file" 

Référence sur le système de fichiers: http://fr.cppreference.com/w/cpp/filesystem

  • std :: filesystem :: path :: filename
  • std :: filesystem :: path :: stem

Comme suggéré par @RoiDanto , pour le formatage de sortie, std::out peut entourer la sortie de citations, par exemple:

 filename and extension: "file.ext" 

Vous pouvez convertir std::filesystem::path en std::ssortingng par p.filename().ssortingng() si c'est ce dont vous avez besoin, par exemple:

 filename and extension: file.ext 

Pas le code, mais voici l’idée:

  1. Lire un std::ssortingng du stream d’entrée ( std::ifstream ), chaque instance lue sera le chemin complet
  2. Faites un find_last_of sur la chaîne pour le \
  3. Extraire une sous-chaîne de cette position à la fin, cela vous donnera maintenant le nom du fichier
  4. Faites un find_last_of pour . , et une sous-chaîne de chaque côté vous donnera un nom + une extension.

J’utilise également cet extrait pour déterminer le caractère de barre oblique approprié:

 boost::filesystem::path slash("/"); boost::filesystem::path::ssortingng_type preferredSlash = slash.make_preferred().native(); 

puis remplacez les barres obliques par la barre oblique préférée pour le système d’exploitation. Utile si l’on déploie constamment entre Linux / Windows.

Pour les machines Linux ou Unix, le système d’exploitation a deux fonctions traitant des noms de chemin et de fichier. Utilisez man 3 basename pour obtenir plus d’informations sur ces fonctions. L’avantage d’utiliser les fonctionnalités fournies par le système est que vous n’avez pas à installer boost ou à écrire vos propres fonctions.

 #include  char *dirname(char *path); char *basename(char *path); 

Exemple de code de la page de manuel:

  char *dirc, *basec, *bname, *dname; char *path = "/etc/passwd"; dirc = strdup(path); basec = strdup(path); dname = dirname(dirc); bname = basename(basec); printf("dirname=%s, basename=%s\n", dname, bname); 

En raison du type d’argument non-const de la fonction basename (), il est un peu simple à utiliser avec ce code C ++. Voici un exemple simple de ma base de code:

 ssortingng getFileStem(const ssortingng& filePath) const { char* buff = new char[filePath.size()+1]; strcpy(buff, filePath.c_str()); ssortingng tmp = ssortingng(basename(buff)); ssortingng::size_type i = tmp.rfind('.'); if (i != ssortingng::npos) { tmp = tmp.substr(0,i); } delete[] buff; return tmp; } 

L’utilisation de new / delete n’est pas un bon style. J’aurais pu le mettre dans un bloc try / catch au cas où quelque chose se produirait entre les deux appels.