如何从单独的字符串(安全地)构建完整路径字符串?

C + + 是否有任何与 python 函数 os.path.join等价的东西?基本上,我正在寻找的东西,结合两个(或更多)部分的文件路径,使您不必担心,以确保这两个部分完美地结合在一起。如果是 QT,那也很酷。

基本上,我花了一个小时来调试一些代码,其中至少有一部分是因为 root + filename必须是 root/ + filename,我希望在将来避免这种情况。

105924 次浏览

Only as part of Boost.Filesystem library. Here is an example:

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

Here is an example of compiling and running (platform specific):

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

If you want to do this with Qt, you can use QFileInfo constructor:

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

Check out QDir for that:

QString path = QDir(dirPath).filePath(fileName);

At least in Unix / Linux, it's always safe to join parts of a path by /, even if some parts of the path already end in /, i.e. root/path is equivalent to root//path.

In this case, all you really need is to join things on /. That said, I agree with other answers that boost::filesystem is a good choice if it is available to you because it supports multiple platforms.

In Qt, just use / in code when using Qt API (QFile, QFileInfo). It will do the right thing on all platforms. If you have to pass a path to a non-Qt function, or want to format it for displaying it to the user, use QDir:toNativeSeparators() e.g.:

QDir::toNativeSeparators( path );

It will replace / by the native equivalent (i.e. \ on Windows). The other direction is done via QDir::fromNativeSeparators().

Similar to @user405725's answer (but not using boost), and mentioned by @ildjarn in a comment, this functionality is available as part of std::filesystem. The following code compiles using Homebrew GCC 9.2.0_1 and using the flag --std=c++17:

#include <iostream>
#include <filesystem>
namespace fs = std::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;
}

With C++11 and Qt you can do this:

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