You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ std::filesystem::path转std::string的编码问题及解决

C++17 filesystem路径处理崩溃与调试乱码问题

问题场景

遍历目录获取文件名时,遇到含特定字符的路径会触发崩溃。使用Visual Studio 2022编译,C标准为C17。

原始代码

#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

问题简化排查

将问题简化为以下代码,同样在path.string()处崩溃,确认是字符・(Unicode编码\u30FB)导致的问题:

#include <filesystem>

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

注:path.wstring()、path.u8string()转换均正常,但业务需要char*类型以适配ImGui::Text或FMOD等API。

编码转换的乱码问题

尝试用Win32 API将wstring转为UTF-8编码的string时,调试界面显示乱码(例如得到"・"而非预期的UTF-8编码字节序列),转换代码如下:

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

std::string ws2s(const std::wstring& wstr)
{
    int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
    std::string str;
    str.reserve(len);
    WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, str.data(), len, nullptr, nullptr);
    return str;
}

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

问题根源解决

后续发现是Visual Studio调试界面的编码问题导致UTF-8内容显示异常:vector<string>中实际存储的是正确的UTF-8编码内容,仅调试器显示乱码。只需在监视窗口中给变量(如vec[0])追加,s8,即可强制调试器以UTF-8编码解析并正确显示内容。

疑问

微软为何执着于UTF-16?UTF-8难道不够好用吗?


内容的提问来源于stack exchange,提问作者guruguru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:50:18