วิธีสร้างสตริงเส้นทางแบบเต็ม (อย่างปลอดภัย) จากสตริงแยกกัน


91

C ++ มีคุณสมบัติเทียบเท่ากับฟังก์ชันของ python os.path.joinหรือไม่? โดยพื้นฐานแล้วฉันกำลังมองหาสิ่งที่รวมสองส่วน (หรือมากกว่า) ของเส้นทางไฟล์เพื่อที่คุณจะได้ไม่ต้องกังวลว่าทั้งสองส่วนจะพอดีกันอย่างสมบูรณ์แบบ ถ้าอยู่ใน Qt มันก็เจ๋งเหมือนกัน

โดยทั่วไปฉันใช้เวลาหนึ่งชั่วโมงในการดีบักโค้ดบางส่วนและอย่างน้อยส่วนหนึ่งก็เป็นเพราะroot + filenameต้องเป็นroot/ + filenameและฉันกำลังพยายามหลีกเลี่ยงสิ่งนั้นในอนาคต


อาจจะห่างไกลที่เกี่ยวข้อง: stackoverflow.com/questions/5772992/... (โดยเฉพาะที่เกี่ยวข้องกับการว่าคำถามคือการเพิ่มของcomplete)
Lightness แข่งในวงโคจร

คำตอบ:


45

ตรวจสอบQDirสำหรับสิ่งนั้น:

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

3
ระวังว่า Qt คือ GPL อาจเป็นตัวแบ่งข้อตกลงสำหรับการใช้งานจำนวนมาก
rustyx

4
@RustyX มันเป็น LGPL ต้องเป๊ะ
Pa_

100

เป็นส่วนหนึ่งของไลบรารี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

1
นอกจากนี้ยังอยู่ใน TR2 ซึ่งมีแนวโน้มว่าจะเริ่มจัดส่งพร้อมกับคอมไพเลอร์ในปีหน้า
ildjarn

1
@ วลาด: ใช่มันไม่สามารถค้นพบได้ง่ายๆ แต่ฉันเกลียดการคลิกลิงก์ Boost doc และรู้ตัวว่าฉันกำลังดูเวอร์ชันเก่าอยู่นานฉันจึงแก้ไขลิงก์เฉพาะเวอร์ชันของผู้คนเมื่อฉันเจอลิงก์เหล่านี้ :-P
ildjarn

1
@ildjarn: ซึ่งดูเหมือนจะใช้งานได้ดีในตอนนี้ ... แต่รอจนกว่าพวกเขาจะเปลี่ยนแปลงบางอย่างเกี่ยวกับไซต์หรือเอกสารสำหรับไลบรารีที่กำหนด มันแย่ยิ่งกว่าการปล่อยลิงค์เฉพาะเวอร์ชันจากนั้น
Fred Nurk

1
@ เฟรด: เห็นได้ชัดว่าหากฟังก์ชันหรือคำถามเป็นเวอร์ชันเฉพาะฉันจะไม่เปลี่ยน URL ในกรณีนี้ฉันไม่ได้ทำ
ildjarn

1
@ildjarn: คุณจะคาดเดาได้อย่างไรว่าไลบรารีที่กำหนดจะเปลี่ยนแปลงในอนาคตเพื่อให้คุณสามารถรู้ได้ว่าคำตอบทั้งหมดที่คุณแก้ไขจะเหมาะสมกับเวอร์ชันในอนาคตทั้งหมดหรือไม่
Fred Nurk

28

คล้ายกับ@ user405725 's คำตอบ ( แต่ไม่ได้ใช้เพิ่ม) และกล่าวถึงโดย@ildjarnในความคิดเห็นการทำงานนี้สามารถใช้ได้เป็นส่วนหนึ่งของมาตรฐาน :: ระบบแฟ้ม โค้ดต่อไปนี้คอมไพล์โดยใช้ Homebrew GCC 9.2.0_1 และใช้แฟล็ก--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;
}

4
ตั้งแต่ C ++ 17 สิ่งนี้ถูกรวมเข้ากับส่วนหัว <filesystem> (ไม่ใช่การทดลอง) ดูen.cppreference.com/w/cpp/filesystem
Eli_B

จะได้ผลไหมถ้าเรามี "/ tmp /"
Mehdi

9

อย่างน้อยใน Unix / Linux การรวมบางส่วนของเส้นทางโดยปลอดภัยเสมอ/แม้ว่าบางส่วนของเส้นทางจะสิ้นสุดลงแล้ว/เช่นroot/pathเทียบเท่ากับroot//path.

/ในกรณีนี้สิ่งที่คุณต้องการจริงๆคือการเข้าร่วมสิ่งที่เกี่ยวกับ ที่กล่าวว่าฉันเห็นด้วยกับคำตอบอื่น ๆ ที่boost::filesystemเป็นทางเลือกที่ดีหากคุณสามารถใช้ได้เนื่องจากรองรับหลายแพลตฟอร์ม


2
QT ไม่เชื่อเรื่องพระเจ้ากับตัวคั่นเส้นทาง หากคุณพิมพ์พา ธ สัมบูรณ์ของไฟล์บน Windows ผลลัพธ์คือ "C: /Users/Name/MyFile.txt" โดยมีตัวคั่น / (unix) boost :: filesystem ดีมาก แต่ในความคิดของฉันถ้าโปรเจ็กต์เป็นแบบ Qt ก็ไม่จำเป็นต้องเพิ่ม dependecy เพื่อเพิ่มไลบรารี่
LoSciamano

7

หากคุณต้องการทำสิ่งนี้ด้วย Qt คุณสามารถใช้ตัวQFileInfoสร้าง:

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

4

ด้วย 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

ใน Qt ใช้/ในโค้ดเมื่อใช้ Qt API ( QFile, QFileInfo) มันจะทำสิ่งที่ถูกต้องในทุกแพลตฟอร์ม หากคุณต้องส่งเส้นทางไปยังฟังก์ชันที่ไม่ใช่ Qt หรือต้องการจัดรูปแบบเพื่อแสดงต่อผู้ใช้ให้ใช้QDir:toNativeSeparators()เช่น:

QDir::toNativeSeparators( path );

มันจะแทนที่/ด้วยค่าเทียบเท่าดั้งเดิม (เช่น\บน Windows) ทิศทางอื่นจะทำผ่านQDir::fromNativeSeparators().

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.