Bagaimana cara membuat string jalur lengkap (aman) dari string terpisah?

91

Apakah C ++ memiliki fungsi yang setara dengan python os.path.join? Pada dasarnya, saya mencari sesuatu yang menggabungkan dua (atau lebih) bagian dari jalur file sehingga Anda tidak perlu khawatir tentang memastikan kedua bagian cocok satu sama lain. Kalau di Qt, itu keren juga.

Pada dasarnya saya menghabiskan satu jam men-debug beberapa kode dan setidaknya sebagian karena root + filenameharus root/ + filename, dan saya ingin menghindarinya di masa depan.

sas4740
sumber
Mungkin jauh terkait: stackoverflow.com/questions/5772992/... (khusus, terkait dengan yang dimaksud adalah dorongan ini complete)
Lightness Races di Orbit

Jawaban:

45

Lihat QDir untuk itu:

QString path = QDir(dirPath).filePath(fileName);
Stephen Chu
sumber
3
Berhati-hatilah bahwa Qt adalah GPL. Mungkin menjadi pemecah kesepakatan untuk banyak kegunaan.
rustyx
4
@RustyX itu LGPL, tepatnya.
Pa_
99

Hanya sebagai bagian dari pustaka Boost.Filesystem . Berikut ini contohnya:

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

Berikut adalah contoh kompilasi dan pengoperasian (khusus platform):

$ g++ ./test.cpp -o test -lboost_filesystem -lboost_system
$ ./test 
/tmp/foo.txt
Azeem
sumber
1
Ini juga di TR2, yang kemungkinan akan mulai dikirim dengan compiler tahun depan.
ildjarn
1
@Vlad: Ya, ini tidak mudah ditemukan, tapi saya benci mengklik tautan dokumen Boost dan terlambat menyadari bahwa saya melihat versi lama, jadi saya mengedit tautan khusus versi orang ketika saya menemukannya. :-P
ildjarn
1
@ildjarn: Yang tampaknya bekerja dengan baik sekarang ... tapi tunggu sampai mereka mengubah sesuatu tentang situs atau dokumen untuk perpustakaan yang diberikan. Ini lebih buruk daripada meninggalkan tautan khusus versi sejak saat itu.
Fred Nurk
1
@Fred: Jelas jika fungsionalitas atau pertanyaan kebetulan ada pada versi tertentu, saya tidak mengubah URL. Dalam hal ini, tidak, jadi saya lakukan.
ildjarn
1
@ildjarn: Bagaimana Anda memprediksi perubahan perpustakaan tertentu di masa mendatang sehingga Anda dapat mengetahui apakah semua jawaban yang Anda edit akan masuk akal untuk semua versi mendatang?
Fred Nurk
24

Mirip dengan jawaban @ user405725 (tetapi tidak menggunakan boost), dan disebutkan oleh @ildjarn dalam komentar, fungsionalitas ini tersedia sebagai bagian dari std :: filesystem . Kode berikut dikompilasi menggunakan Homebrew GCC 9.2.0_1 dan menggunakan bendera --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
sumber
4
Pada C ++ 17, ini digabungkan ke dalam header <filesystem> (non-eksperimental). Lihat en.cppreference.com/w/cpp/filesystem .
Eli_B
9

Setidaknya di Unix / Linux, itu selalu aman untuk bergabung dengan bagian dari sebuah jalur dengan /, bahkan jika beberapa bagian dari jalur tersebut sudah diakhiri /, yaitu root/pathsetara dengan root//path.

Dalam hal ini, yang benar-benar Anda butuhkan hanyalah menggabungkan berbagai hal /. Karena itu, saya setuju dengan jawaban lain yang boost::filesystemmerupakan pilihan yang baik jika tersedia untuk Anda karena mendukung banyak platform.

terus terang
sumber
2
QT agnostik terhadap pemisah jalur. Jika Anda mencetak path absolut dari sebuah file di Windows, hasilnya adalah "C: /Users/Name/MyFile.txt" dengan pemisah / (unix). boost :: filesystem sangat bagus tetapi, menurut saya, jika proyek ini berbasis Qt, tidak perlu menambahkan dependecy untuk perpustakaan boost.
LoSciamano
7

Jika Anda ingin melakukan ini dengan Qt, Anda dapat menggunakan QFileInfokonstruktor:

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

Dengan C ++ 11 dan Qt Anda dapat melakukan ini:

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

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

Pemakaian:

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

Di Qt, cukup gunakan /dalam kode saat menggunakan Qt API ( QFile, QFileInfo). Itu akan melakukan hal yang benar di semua platform. Jika Anda harus meneruskan jalur ke fungsi non-Qt, atau ingin memformatnya untuk ditampilkan kepada pengguna, gunakan QDir:toNativeSeparators()misalnya:

QDir::toNativeSeparators( path );

Ini akan diganti /dengan padanan asli (yaitu \pada Windows). Arah lain dilakukan melalui QDir::fromNativeSeparators().

Frank Osterfeld
sumber