Comment puis-je extraire le fichier nom et extension d'un chemin en C++
J'ai une liste de fichiers stockés dans un .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?
Vous devez vous connecter pour publier un commentaire.
Pour extraire un nom de fichier sans extension, utiliser boost::filesystem::chemin d'accès::souches au lieu de laid std::string::find_last_of(".")
std::experimental::filesystem
respstd::filesystem
. Voir le post de Yuchen Zhong ci-dessous.Si vous voulez un moyen sûr (c'est à dire portable entre les plates-formes et de ne pas mettre que des hypothèses sur le chemin), je vous recommande d'utiliser
boost::filesystem
.Il serait en quelque sorte ressembler à ceci:
Ensuite, vous pouvez extraire des données différentes de ce chemin. Voici la documentation de la trajectoire de l'objet.
BTW: rappelez-vous Aussi que pour utiliser le chemin comme
vous avez besoin pour échapper à la
\
dans une chaîne de caractères littérale:Ou de l'utilisation
/
à la place:Ceci ne s'applique qu'à spécifier les chaînes littérales dans
""
citations, le problème n'existe pas lorsque vous chargez des chemins à partir d'un fichier.Vous aurez à lire vos noms de fichiers à partir du fichier dans
std::string
. Vous pouvez utiliser la chaîne de l'extraction de l'opérateur destd::ostream
. Une fois que vous avez votre nom de fichier dans unstd::string
, vous pouvez utiliser lestd::string::find_last_of
méthode pour trouver le dernier séparateur.Quelque chose comme ceci:
Pour C++17:
La référence sur le système de fichiers: http://en.cppreference.com/w/cpp/filesystem
Comme suggéré par @RoiDanto, pour le formatage de sortie,
std::out
peuvent entourer la sortie avec des citations, par exemple:Vous pouvez convertir
std::filesystem::path
àstd::string
parp.filename().string()
si c'est ce que vous avez besoin, par exemple:std::filesystem::path
àstd::string
afin d'être en mesure d'utiliserstd::cout
. en.cppreference.com/w/cpp/filesystem/path/filename Mais si vous pensez le contraire, n'hésitez pas à commenter ou modifier les poster à nouveau.std::cout
peut compter sur la conversion implicite. Cependant, puisque les commentaires aprèsstd::cout
dire fichier.poste et fichier, soit.string()
doit être ajouté aux commentaires ou qu'ils devraient être "fichier.ext" et "fichier". Avec Visual C++ il y a en effet pas de différence (même sansstring()
la sortie est sans les guillemets), mais avec gcc 6.1 la sortie est avec des guillemets si.string()
est omis. Voir coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3Pas le code, mais voici l'idée:
std::string
à partir du flux d'entrée (std::ifstream
), chaque instance de lecture sera le chemin d'accès completfind_last_of
sur la chaîne de l'\
find_last_of
pour.
, et une sous-chaîne de chaque côté de vous donner le nom + extension./
ainsi. Et je ne sais même pas si il existe plus de mises en garde dans les spécifications de chemin, si mon raisonnement est simple: si il y a une bonne bibliothèque qui fait ce que je veux, je dois l'utiliser, parce qu'il permettra d'atteindre mon objectif sans doute mieux que je peux. 😉boost::insects::disperser<T>
modèle générique pour qui? 🙂J'utilise aussi cet extrait de code pour déterminer le caractère de barre oblique:
puis de remplacer les barres obliques, avec la préférée de slash pour les OS. Utile si l'on est constamment déploiement d'entre Linux/Windows.
Pour linux ou unix, le système d'exploitation dispose de deux fonctions de traiter avec chemin d'accès et les noms de fichier. utilisez man 3 basename pour obtenir plus d'informations sur ces fonctions.
L'avantage de l'utilisation du système de fonctionnalités, c'est que vous n'avez pas à installer boost ou qui ont besoin d'écrire vos propres fonctions.
Exemple de code à partir de la page de man:
En raison de la non-const type d'argument de la basename() de la fonction, c'est un peu non-linéaire à l'aide de ce à l'intérieur du code C++. Voici un simple exemple de mon code de base:
L'utilisation de new/delete n'est pas un bon style. Je pouvais le mettre dans un try/catch
bloc dans le cas où quelque chose s'est passé entre les deux appels.
Nickolay Merkin et Yuchen Zhong réponses sont grands, mais d'après les commentaires, vous pouvez voir que ce n'est pas tout à fait exact.
La conversion implicite en std::string lors de l'impression se terminera le nom de fichier dans les citations. Les commentaires ne sont pas fiables.
path::filename()
etpath::stem()
renvoie un nouvel objet de chemin etpath::string()
renvoie une référence à une chaîne. Donc quelque chose commestd::cout << file_path.filename().string() << "\n"
pourraient causer des problèmes avec des pendants de référence depuis la chaîne que les points de référence à peut-être été détruits.