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
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:
std::ssortingng
du stream d’entrée ( std::ifstream
), chaque instance lue sera le chemin complet find_last_of
sur la chaîne pour le \
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.