Как построить полную строку пути (безопасно) из отдельных строк? - PullRequest
80 голосов
/ 09 июня 2011

Есть ли в C ++ эквивалент функции Python os.path.join?По сути, я ищу что-то, что объединяет две (или более) части пути к файлу, чтобы вам не пришлось беспокоиться о том, чтобы обе части идеально совпали друг с другом.Если бы он был в Qt, это тоже было бы здорово.

По сути, я потратил час на отладку некоторого кода, и, по крайней мере, его часть была из-за того, что root + filename должен был быть root/ + filename, и я стараюсь избегатьчто в будущем.

Ответы [ 7 ]

94 голосов
/ 09 июня 2011

Только как часть Boost.Filesystem библиотеки.Вот пример:

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

Вот пример компиляции и запуска (зависит от платформы):

$ g++ ./test.cpp -o test -lboost_filesystem -lboost_system
$ ./test 
/tmp/foo.txt
37 голосов
/ 09 июня 2011

Проверьте QDir для этого:

QString path = QDir(dirPath).filePath(fileName);
18 голосов
/ 25 апреля 2016

Аналогично ответу @ user405725 (но без использования boost) и упоминается @ ildjarn в комментарии, эта функциональность доступна как часть std: : экспериментальная :: файловая система . Следующий код компилируется с использованием 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;
}
8 голосов
/ 09 июня 2011

По крайней мере в Unix / Linux всегда безопасно соединять части пути на /, даже если некоторые части пути уже заканчиваются на /, то есть root/path эквивалентно root//path.

В этом случае все, что вам действительно нужно, это присоединиться к вещам на /. Тем не менее, я согласен с другими ответами, что boost::filesystem является хорошим выбором, если он доступен для вас, поскольку он поддерживает несколько платформ.

6 голосов
/ 09 июня 2011

Если вы хотите сделать это с Qt, вы можете использовать QFileInfo constructor:

QFileInfo fi( QDir("/tmp"), "file" );
QString path = fi.absoluteFilePath();
3 голосов
/ 23 июля 2016

С C ++ 11 и Qt вы можете сделать это:

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

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

Использование:

QString path = join("/tmp", "dir", "file"); // /tmp/dir/file
3 голосов
/ 10 июня 2011

В Qt просто используйте / в коде при использовании Qt API (QFile, QFileInfo). Это будет правильно делать на всех платформах. Если вам нужно передать путь к функции не из Qt, или вы хотите отформатировать ее для отображения пользователю, используйте QDir:toNativeSeparators() например ::

QDir::toNativeSeparators( path );

Он заменит / на собственный эквивалент (т. Е. \ в Windows). Другое направление осуществляется через QDir::fromNativeSeparators().

...