преобразовать путь к файлу из Windows в Linux и обратно, используя boost :: filesystem

Это я, или boost :: filesystem :: path :: make_preferred не преобразует "\" в "/"?

davidan @ kempt: ~ / Documents / prog / work! $ ../practice/./path_info c: \ pitou foo / bar \ baa.txt
составной путь:
cout ‹< ------ -------: "c: pitou / foo / bar \ baa.txt"
make_preferred () ----------: "c: pitou / foo / bar \ baa.txt "

Я скорее надеялся на

c: \ pitou \ foo \ bar \ baa.txt

на окнах и

/pitou/foo/bar/baa.txt

(или что-то похожее) на POSIX

источник находится здесь: boost :: filesystem tutorial


person Sassinak    schedule 05.04.2013    source источник
comment
не можете ли вы использовать обычные переменные среды, например HOME и getenv их?   -  person Basile Starynkevitch    schedule 05.04.2013
comment
включено в path.hpp: ›# ifdef BOOST_WINDOWS_API typedef wchar_t value_type; BOOST_STATIC_CONSTEXPR тип_значения предпочтительный_разделитель = L '\\'; # иначе typedef char value_type; BOOST_STATIC_CONSTEXPR тип_значения предпочтительный_разделитель = '/'; # endif Значит, это уже нужно решать, не так ли?   -  person Sassinak    schedule 06.04.2013
comment
нет, это не так ... ›› path & make_preferred (); Эффекты: содержащееся имя пути преобразуется в предпочтительный собственный формат. [Примечание. В Windows косая черта заменяется обратной косой чертой. В POSIX эффекта нет. - конец примечания] Мне пришлось делать это вручную с помощью std :: replace в условии ifdef posix   -  person Sassinak    schedule 15.05.2013
comment
Сделать make_preferred у меня тоже не получилось. Однако я решил свою проблему с помощью path.string () (взгляните на theboostcpplibraries.com/boost.filesystem -путь). Я надеюсь, что это помогает.   -  person agodinhost    schedule 15.12.2014


Ответы (3)


Причина, по которой это не обрабатывается в Linux, хорошо объясняется здесь:

http://theboostcpplibraries.com/boost.filesystem-paths

Цитировать:

Если пример 35.5 выполняется в Linux, возвращаемые значения будут другими. Большинство функций-членов возвращают пустую строку, за исключением relative_path () и filename (), которые возвращают «C: \ Windows \ System». Это означает, что строка «C: \ Windows \ System» интерпретируется как имя файла в Linux, что понятно, учитывая, что это не переносимая кодировка пути и не зависящая от платформы кодировка в Linux. Следовательно, у Boost.Filesystem нет другого выбора, кроме как интерпретировать его как имя файла.

person elegant dice    schedule 26.06.2016

Закончилось так:

string f = filename;
#       ifdef BOOST_POSIX_API   //workaround for user-input files
            std::replace(f.begin(), f.end(), '\\', '/');        
#       endif

Должна быть причина, по которой это еще не решено ...?

person Sassinak    schedule 15.05.2013

Здесь не используется boost, но я реализовал оба направления преобразования вручную.

FileSystemPathUtils.hpp:

#pragma once

#include <string>

static const char *const WSL_FILE_PATH_HEADER = "/mnt";
static const char WINDOWS_FILE_PATH_SEPARATOR = '\\';
static const char UNIX_FILE_PATH_SEPARATOR = '/';

std::string windows_to_unix_file_path(std::string file_path, bool is_wsl = true);

std::string unix_to_windows_file_path(std::string file_path, bool is_wsl = true);

std::string windows_path_to_host_operating_system_path(std::string file_path, bool is_wsl = true);

FileSystemPathUtils.cpp:

#include "FileSystemPathUtils.hpp"

#include <string>
#include <algorithm>
#include <sstream>
#include <utility>
#include <cstring>

std::string windows_to_unix_file_path(std::string file_path, bool is_wsl) {
    // Replace the slashes
    std::replace(file_path.begin(), file_path.end(), WINDOWS_FILE_PATH_SEPARATOR, UNIX_FILE_PATH_SEPARATOR);

    // Convert the drive letter to lowercase
    std::transform(file_path.begin(), file_path.begin() + 1, file_path.begin(),
                   [](unsigned char character) {
                       return std::tolower(character);
                   });

    // Remove the colon
    const auto drive_letter = file_path.substr(0, 1);
    const auto remaining_path = file_path.substr(2, file_path.size() - 2);
    file_path = drive_letter + remaining_path;

    std::stringstream stringstream;

    if (is_wsl) {
        stringstream << WSL_FILE_PATH_HEADER;
    }

    stringstream << "/";
    stringstream << file_path;

    return stringstream.str();
}

std::string unix_to_windows_file_path(std::string file_path, bool is_wsl) {
    if (is_wsl) {
        file_path = file_path.erase(0, strlen(WSL_FILE_PATH_HEADER));
    }

    // Delete the leading forward slash
    file_path.erase(0, 1);

    // Convert the drive letter to uppercase
    std::transform(file_path.begin(), file_path.begin() + 1, file_path.begin(),
                   [](unsigned char character) {
                       return std::toupper(character);
                   });

    // Replace the slashes
    std::replace(file_path.begin(), file_path.end(), UNIX_FILE_PATH_SEPARATOR,
                 WINDOWS_FILE_PATH_SEPARATOR);

    std::stringstream stringstream;
    stringstream << file_path.at(0);
    stringstream << ":";
    stringstream << file_path.substr(1, file_path.size() - 1);

    return stringstream.str();
}

std::string windows_path_to_host_operating_system_path(std::string file_path, bool is_wsl) {
#ifdef _WIN32
    return file_path;

#else
    return windows_to_unix_file_path(std::move(file_path), is_wsl);

#endif
}
person BullyWiiPlaza    schedule 12.10.2019