web-dev-qa-db-fra.com

Comment construire une chaîne de chemin complet (en toute sécurité) à partir de chaînes séparées?

Est-ce que C++ a un équivalent à la fonction de python os.path.join? Fondamentalement, je recherche quelque chose qui combine deux (ou plus) parties d’un chemin de fichier, de sorte que vous n’ayez pas à vous soucier de l’association parfaite des deux parties. Si c'est en Qt, ce serait cool aussi.

En gros, j'ai passé une heure à déboguer du code, dont au moins une partie était dû au fait que root + filename devait être root/ + filename, et je cherche à éviter cela à l'avenir.

80
sas4740

Découvrez QDir pour cela:

QString path = QDir(dirPath).filePath(fileName);
37
Stephen Chu

Seulement dans le cadre de la bibliothèque Boost.Filesystem . Voici un exemple:

#include <iostream>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

int main ()
{
    fs::path dir ("/tmp");
    fs::path file ("foo.txt");
    fs::path full_path = dir / file;
    std::cout << full_path << std::endl;
    return 0;
}

Voici un exemple de compilation et d’exécution (spécifique à la plate-forme):

$ g++ ./test.cpp -o test -lboost_filesystem -lboost_system
$ ./test 
/tmp/foo.txt
94
user405725

Semblable à la réponse de @ user405725 (mais n'utilise pas de boost), et mentionnée par @ ildjarn dans un commentaire, cette fonctionnalité est disponible dans le cadre de - std :: experimental :: système de fichiers . Le code suivant est compilé à l'aide de Microsoft Visual Studio 2015 Community Edition:

#include <iostream>
#include <filesystem>
namespace fs = std::experimental::filesystem;

int main() 
{
    fs::path dir ("/tmp");
    fs::path file ("foo.txt");
    fs::path full_path = dir / file;
    std::cout << full_path << std::endl;
    return 0;
}
19
Shawn Blakesley

Au moins sous Unix/Linux, il est toujours prudent de joindre des parties d’un chemin par /, même si certaines parties du chemin se terminent déjà par /, c'est à dire. root/path est équivalent à root//path.

Dans ce cas, tout ce dont vous avez besoin est de joindre des éléments sur /. Cela dit, je suis d’accord avec d’autres réponses que boost::filesystem est un bon choix s’il est disponible, car il prend en charge plusieurs plates-formes.

8
frankc

Si vous voulez faire cela avec Qt, vous pouvez utiliser le constructeur QFileInfo:

QFileInfo fi( QDir("/tmp"), "file" );
QString path = fi.absoluteFilePath();
6
LoSciamano

Dans Qt, utilisez simplement / Dans le code lorsque vous utilisez l'API Qt (QFile, QFileInfo). Il fera la bonne chose sur toutes les plateformes. Si vous devez passer un chemin vers une fonction non-Qt ou si vous voulez le formater pour l’afficher à l’utilisateur, utilisez QDir:toNativeSeparators() par exemple:

QDir::toNativeSeparators( path );

Il remplacera / Par son équivalent natif (c'est-à-dire \ Sous Windows). L’autre direction se fait via QDir::fromNativeSeparators().

3
Frank Osterfeld

Avec C++ 11 et Qt, vous pouvez faire ceci:

QString join(const QString& v) {
    return v;
}

template<typename... Args>
QString join(const QString& first, Args... args) {
    return QDir(first).filePath(join(args...));
}

Usage:

QString path = join("/tmp", "dir", "file"); // /tmp/dir/file
3
kainjow