C++ 中 std::filesystem::path 转换为 std::string 的问题

问题描述 投票:0回答:1

我在尝试从目录中获取所有文件名时遇到问题。处理某些字符串时会出现问题,导致错误。下面是代码片段:

#include <filesystem>

int main()
{
    const char* dir = "D:\\Music";
    std::vector<std::string> musicList;

    for (const auto& entry : std::filesystem::recursive_directory_iterator(dir))
    {
        if (entry.is_regular_file())
        {
            musicList.emplace_back(entry.path().string());
        }
    }
}

在处理 L"D:\Music\suki\Angel Note - 月明かりは优しく・・・.mp3" 等字符串时,该问题出现在entry.path().string()处。程序终止并出现错误,指向:

_STD_BEGIN
// We would really love to use the proper way of building error_code by specializing
// is_error_code_enum and make_error_code for __std_win_error, but because:
//   1. We would like to keep the definition of __std_win_error in xfilesystem_abi.h
//   2. and xfilesystem_abi.h cannot include <system_error>
//   3. and specialization of is_error_code_enum and overload of make_error_code
//      need to be kept together with the enum (see limerick in N4950 [temp.expl.spec]/8)
// we resort to using this _Make_ec helper.
_NODISCARD inline error_code _Make_ec(__std_win_error _Errno) noexcept { // make an error_code
    return { static_cast<int>(_Errno), _STD system_category() };
}

[[noreturn]] inline void _Throw_system_error_from_std_win_error(const __std_win_error _Errno) {
    _THROW(system_error{ _Make_ec(_Errno) });  // Here occur error!
}
_STD_END

哦,我是在vs2022中编译的代码,c++标准是17。

经过调查,我将问题简化为:

#include <filesystem>

int main()
{
    std::filesystem::path path = L"・";
    auto str = path.string();
}

path.string() 也出现了类似的问题。使用 L"\u30FB" 进一步简化后,我发现字符 ・ 表示为“\u30FB”。

虽然 path.wstring()、path.u8string() 和其他字符串转换工作得很好,但我需要一个 char* 用于 API,例如 ImGui::Text(str) 或 FMOD 的 API。尝试使用 codecvt、Win32 API 或 ICU 将 wstring 转换为字符串会导致出现乱码文本,例如“ã»”:

#include <filesystem>
#include <Windows.h>

std::string ws2s(const std::wstring& wstr)
{
    int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
    char* utf8String = new char[utf8Len];
    WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, utf8String, utf8Len, nullptr, nullptr);
    return utf8String;
}

int main()
{
    std::filesystem::path path = L"\u30FB";
    auto str = ws2s(path.wstring());
}

生成的 str 是“ãf»”而不是“\u30FB”。

有没有可靠的方法可以有效处理这种情况?

c++ windows utf-8 std-filesystem
1个回答
0
投票

这是编码问题。将其添加到程序的开头,问题应该得到解决:

    const char* const localeName = "ja_JP.utf-8";

    // instruct C standard library that Japanese will be used with UTF-8 encoding
    std::setlocale(LC_ALL, localeName);

    // instruct C++ standard library that Japanese will be used with UTF-8 encoding for example in std::string, std::ostream
    std::locale::global(std::locale(localeName));

    // use system locale (language and encoding), when printing data to std::cout
    std::cout.imbue(std::locale{""}});

我也遇到了类似的问题

boost::filesystem::path
,这解决了问题。

© www.soinside.com 2019 - 2024. All rights reserved.