How to build a full path string (safely) from separate strings?
Does C++ have any equivalent to python's function os.path.join
? Basically, I'm looking for something that combines two (or more) parts of a file path so that you don't have to worry about making sure the two parts fit together perfectly.开发者_开发技巧 If it's in Qt, that would be cool too.
Basically I spent an hour debugging some code and at least part of it was because root + filename
had to be root/ + filename
, and I'm looking to avoid that in the future.
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
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;
}
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.
If you want to do this with Qt, you can use QFileInfo
constructor:
QFileInfo fi( QDir("/tmp"), "file" );
QString path = fi.absoluteFilePath();
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
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()
.
Here is a very simple C++11 friendly alternative for the people who have neither Boost, Qt nor C++17 (taken from here):
std::string pathJoin(const std::string& p1, const std::string& p2)
{
char sep = '/';
std::string tmp = p1;
#ifdef _WIN32
sep = '\\';
#endif
// Add separator if it is not included in the first path:
if (p1[p1.length()] != sep) {
tmp += sep;
return tmp + p2;
} else {
return p1 + p2;
}
}
精彩评论