Як побудувати повний рядок шляху (безпечно) з окремих рядків?


91

Чи має C ++ еквівалент функції python os.path.join? В основному, я шукаю щось, що поєднує дві (або більше) частини шляху до файлу, щоб вам не довелося турбуватися про те, щоб ці частини ідеально поєднувались. Якщо це в Qt, це теж було б круто.

В основному я витратив годину на налагодження деякого коду, і принаймні частина його була тому, root + filenameщо так мало бути root/ + filename, і я прагну цього уникнути в майбутньому.


Можливо, віддалено пов'язані: stackoverflow.com/questions/5772992/… (зокрема, пов'язане з цим питанням - імпульс complete)
Гонки легкості на орбіті

Відповіді:


45

Перевірте QDir для цього:

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

3
Остерігайтеся, що Qt - це GPL. Може бути переривником угод для багатьох цілей.
rustyx

3
@RustyX це LGPL, якщо бути точнішим.
Pa_

98

Лише як частина бібліотеки 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
@Vlad: Так, це непросто виявити, але я ненавиджу натискати посилання Boost doc і із запізненням розуміючи, що я переглядаю стару версію, тому я редагую посилання на конкретні версії людей, коли натрапляю на них. :-P
ildjarn

1
@ildjarn: Що, здається, чудово працює зараз ... але зачекайте, поки вони щось змінять про сайт чи документи для даної бібліотеки. Це гірше, ніж відтепер залишати посилання на конкретну версію.
Fred Nurk,

1
@Fred: Очевидно, що якщо функціональність чи запитання стосуються конкретної версії, я не змінюю URL-адресу. У цьому випадку це не так, тому я зробив.
ildjarn

1
@ildjarn: Як ви передбачаєте, що дана бібліотека зміниться в майбутньому, щоб ви могли знати, чи всі відповіді, які ви редагуєте, будуть мати сенс для всіх майбутніх версій?
Fred Nurk,

24

Подібно до відповіді @ user405725 (але не з використанням boost) і згаданий @ildjarn у коментарі, ця функціональність доступна як частина файлової системи std :: . Наступний код компілюється з використанням 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, це було об’єднано в (не експериментальний) заголовок <файлової системи>. Див. En.cppreference.com/w/cpp/filesystem .
Eli_B

9

Принаймні в Unix / Linux завжди безпечно приєднувати частини шляху /, навіть якщо деякі частини шляху вже закінчуються /, тобто root/pathеквівалентно root//path.

У цьому випадку все, що вам дійсно потрібно, - це приєднатися до справи /. Тим не менш, я погоджуюсь з іншими відповідями, що boost::filesystemє хорошим вибором, якщо він доступний для вас, оскільки він підтримує кілька платформ.


2
QT є агностичним для розділювача шляхів. Якщо ви друкуєте абсолютний шлях до файлу в Windows, виводиться "C: /Users/Name/MyFile.txt" із роздільником / (unix). boost :: файлова система чудова, але, на мій погляд, якщо проект заснований на Qt, немає необхідності додавати залежність для бібліотеки boost.
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().

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.