Wie erstelle ich eine vollständige Pfadzeichenfolge (sicher) aus separaten Zeichenfolgen?

89

Hat C ++ eine Entsprechung zur Python-Funktion os.path.join? Grundsätzlich suche ich nach etwas, das zwei (oder mehr) Teile eines Dateipfads kombiniert, damit Sie sich nicht darum kümmern müssen, dass die beiden Teile perfekt zusammenpassen. Wenn es in Qt ist, wäre das auch cool.

Grundsätzlich habe ich eine Stunde damit verbracht, Code zu debuggen, und zumindest ein Teil davon lag daran root + filename musste root/ + filename, und ich versuche, dies in Zukunft zu vermeiden.

sas4740
quelle
Möglicherweise entfernt verwandt: stackoverflow.com/questions/5772992/… (speziell im Zusammenhang mit dieser Frage steht Boostscomplete )
Leichtigkeitsrennen im Orbit

Antworten:

43

Schauen Sie sich dazu QDir an:

QString path = QDir(dirPath).filePath(fileName);
Stephen Chu
quelle
3
Beachten Sie, dass Qt GPL ist. Könnte ein Deal Breaker für viele Zwecke sein.
Rustyx
2
@RustyX es ist LGPL, um genau zu sein.
Pa_
97

Nur als Teil der Boost.Filesystem- Bibliothek. Hier ist ein Beispiel:

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

Hier ist ein Beispiel für das Kompilieren und Ausführen (plattformspezifisch):

$ g++ ./test.cpp -o test -lboost_filesystem -lboost_system
$ ./test 
/tmp/foo.txt
Azeem
quelle
1
Dies gilt auch für TR2, das voraussichtlich im nächsten Jahr mit Compilern ausgeliefert wird.
ildjarn
1
@Vlad: Ja, es ist nicht leicht zu entdecken, aber ich hasse es, auf Boost-Doc-Links zu klicken und verspätet zu erkennen, dass ich mir eine alte Version anschaue, also bearbeite ich die versionenspezifischen Links von Leuten, wenn ich auf sie stoße. :-P
ildjarn
1
@ildjarn: Was jetzt großartig zu funktionieren scheint ... aber warten Sie, bis sie etwas an der Site oder den Dokumenten für die angegebene Bibliothek ändern. Es ist schlimmer, als von da an den versionenspezifischen Link zu verlassen.
Fred Nurk
1
@Fred: Wenn die Funktionalität oder Frage versionsspezifisch ist, ändere ich die URL natürlich nicht. In diesem Fall ist es nicht so, also habe ich es getan.
ildjarn
1
@ildjarn: Wie können Sie vorhersagen, was sich in einer bestimmten Bibliothek in Zukunft ändern wird, damit Sie wissen, ob alle von Ihnen bearbeiteten Antworten für alle zukünftigen Versionen sinnvoll sind?
Fred Nurk
24

Ähnlich wie bei der Antwort von @ user405725 (jedoch ohne Boost) und von @ildjarn in einem Kommentar erwähnt, ist diese Funktionalität als Teil des std :: -Dateisystems verfügbar . Der folgende Code wird mit Homebrew GCC 9.2.0_1 und dem Flag kompiliert --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;
}
Shawn Blakesley
quelle
4
Ab C ++ 17 wurde dies in den (nicht experimentellen) <Dateisystem> -Header eingefügt. Siehe en.cppreference.com/w/cpp/filesystem .
Eli_B
9

Zumindest unter Unix / Linux ist es immer sicher, Teile eines Pfads zu verknüpfen /, auch wenn einige Teile des Pfads bereits enden /, dh root/pathgleichbedeutend mit root//path.

In diesem Fall müssen Sie sich nur noch anschließen /. Trotzdem stimme ich anderen Antworten zu, boost::filesystemdie eine gute Wahl sind, wenn sie Ihnen zur Verfügung stehen, da sie mehrere Plattformen unterstützen.

frankc
quelle
2
QT ist unabhängig vom Pfadtrenner. Wenn Sie unter Windows den absoluten Pfad einer Datei drucken, lautet die Ausgabe "C: /Users/Name/MyFile.txt" mit dem Trennzeichen / (Unix). boost :: filesystem ist großartig, aber wenn das Projekt Qt-basiert ist, muss meiner Meinung nach keine Abhängigkeit für die Boost-Bibliothek hinzugefügt werden.
LoSciamano
7

Wenn Sie dies mit Qt tun möchten, können Sie den QFileInfoKonstruktor verwenden:

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

Mit C ++ 11 und Qt können Sie dies tun:

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

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

Verwendung:

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

Verwenden Sie /in Qt nur Code, wenn Sie die Qt-API ( QFile, QFileInfo) verwenden. Es wird auf allen Plattformen das Richtige tun. Wenn Sie einen Pfad an eine Nicht-Qt-Funktion übergeben müssen oder ihn formatieren möchten, um ihn dem Benutzer anzuzeigen, verwenden Sie QDir:toNativeSeparators()z.

QDir::toNativeSeparators( path );

Es wird /durch das native Äquivalent ersetzt (dh \unter Windows). Die andere Richtung erfolgt über QDir::fromNativeSeparators().

Frank Osterfeld
quelle