univers1314 2026-01-02 12:04 采纳率: 38.5%
浏览 6

filesystem遍历目录所有文件时报 "在多字节的目标代码页中,没有此 Unicode 字符可以映射到的字符。"

我写了一个很简单的 filesystem遍历目录所有文件,并累加文件MB总和。
但是在碰到奇芭的文件名,或文件夹路径时,会报异常,报错。要怎么才能解决?见下图片:
Capture Exception or Error_PrB : 在多字节的目标代码页中,没有此 Unicode 字符可以映射到的字符。


```c++
#include <iostream>
#include <filesystem>
#include <string>
#include <Windows.h>
#include <string.h>
#include <fstream>
#include <string>
namespace fs = std::filesystem;
using namespace std;

double a1_size = 0;        //字节大小
//************************************************//

void circlePath(string& str)    //
{
    try
    {
        for (auto& i : filesystem::directory_iterator(str))
        {
            if (fs::is_directory(i.path()))
            {
                cout << i.path() << endl;            //报错
                cout << i.path().string() << endl;    //报错
                string str = i.path().string();
                cout << str << endl;                //报错
                circlePath(str);
            }
            else
            {
                cout << i.path().filename() << "        < " << i.file_size() << " >" << "            bs" << endl;
                a1_size += i.file_size();    //显示字节大小
            }
        }
    }
    //-------------------------------------------------------------------------------------------------//
    catch (exception e)
    {
        // 异常处理区域
        cerr << "Capture Exception or Error_PrB : " << e.what() << endl;        //捕获异常,或然后程序结束
    }
}
//*************************************************************************************************//
int main()
{
    string str("D:\\test");
    circlePath(str);
    return 0;
}


![img](https://i-blog.csdnimg.cn/ask/131260f81aed4deb9e86e00a10bbe227.png "#left")

![img](https://i-blog.csdnimg.cn/ask/fafb3f6d3e594288be07df720ec93e81.png "#left")

![img](https://i-blog.csdnimg.cn/ask/f2ca20a5b72d4bb89d88b84b1c7b3942.png "#left")
  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2026-01-02 12:05
    关注

    中午好🌞🌞🌞
    本答案参考通义千问

    你遇到的问题是由于在使用 std::filesystem 遍历文件系统时,路径中包含无法被当前代码页(如 GBK 或 ASCII)正确映射的 Unicode 字符。这通常发生在 Windows 系统中,尤其是当你尝试输出或处理含有 非 ASCII 字符(如中文、日文、韩文等)的文件名或目录名时。


    ✅ 问题分析

    1. 错误信息解析:

      在多字节的目标代码页中,没有此 Unicode 字符可以映射到的字符。
      

      这表示你的程序尝试将一个 Unicode 字符串(如 UTF-8 编码的路径)输出到一个 多字节字符集(MBCS) 的控制台或文件中,而该字符在当前代码页中找不到对应的字符。

    2. 原因:

      • 你在使用 std::filesystem::path 时,它内部存储的是 UTF-16(Windows)或 UTF-8(其他平台)编码的字符串。
      • 但你直接将其转换为 std::string(默认使用本地代码页),导致某些字符无法正确显示。
    3. 关键代码:

      cout << i.path() << endl;            // 报错
      cout << i.path().string() << endl;    // 报错
      string str = i.path().string();       // 报错
      

      这些语句会尝试将 Unicode 路径转换为 std::string,从而引发编码问题。


    ✅ 解决方案

    1. 使用 std::wstringstd::wcout 输出 Unicode 字符串

    Windows 控制台默认使用 GBK 编码,因此需要使用宽字符(wchar_t)来处理 Unicode 路径,并用 std::wcout 输出。

    修改后的代码:

    #include <iostream>
    #include <filesystem>
    #include <string>
    #include <Windows.h>
    #include <fstream>
    #include <string>
    namespace fs = std::filesystem;
    using namespace std;
    
    double a1_size = 0;        // 字节大小
    
    //************************************************//
    void circlePath(wstring& wstr)    //
    {
        try
        {
            for (auto& i : filesystem::directory_iterator(wstr))
            {
                if (fs::is_directory(i.path()))
                {
                    // 使用 wstring 和 wcout 处理 Unicode 路径
                    wcout << i.path() << endl;
                    wcout << i.path().wstring() << endl;
                    wstring wstr = i.path().wstring();
                    wcout << wstr << endl;
                    circlePath(wstr);
                }
                else
                {
                    wcout << i.path().filename() << "        < " << i.file_size() << " >" << "            bs" << endl;
                    a1_size += i.file_size();    // 显示字节大小
                }
            }
        }
        //-------------------------------------------------------------------------------------------------//
        catch (exception e)
        {
            // 异常处理区域
            wcerr << L"Capture Exception or Error_PrB : " << e.what() << endl;        // 捕获异常,或然后程序结束
        }
    }
    //*************************************************************************************************//
    int main()
    {
        wstring wstr(L"D:\\test");  // 使用 wstring 存储路径
        circlePath(wstr);
        wcout << L"Total size: " << a1_size << L" bytes" << endl;
        return 0;
    }
    

    2. 设置控制台为 UTF-8 支持

    如果你希望控制台能够正确显示 Unicode 字符,可以设置控制台为 UTF-8 编码。

    添加以下代码在 main() 中:

    SetConsoleOutputCP(CP_UTF8);  // 设置控制台输出为 UTF-8
    

    完整修改后 main() 函数示例:

    int main()
    {
        SetConsoleOutputCP(CP_UTF8);  // 设置控制台输出为 UTF-8
        wstring wstr(L"D:\\test");
        circlePath(wstr);
        wcout << L"Total size: " << a1_size << L" bytes" << endl;
        return 0;
    }
    

    3. 使用 std::filesystem::u8path()(C++17+)

    如果你使用的是 C++17 或更高版本,可以考虑使用 std::filesystem::u8path() 来处理 UTF-8 字符串,避免编码转换问题。

    示例:

    std::filesystem::path p = std::filesystem::u8path("D:\\test");
    

    ✅ 总结解决方案(有序列表)

    1. std::string 替换为 std::wstring

      • 所有路径变量改为 wstring 类型,以支持 Unicode 字符。
    2. 使用 std::wcoutstd::wcerr

      • 输出 Unicode 字符串时,使用宽字符流(wcout, wcerr)而非 cout
    3. 设置控制台为 UTF-8 编码

      • 使用 SetConsoleOutputCP(CP_UTF8),确保控制台能正确显示 Unicode 字符。
    4. 使用 std::filesystem::u8path()(C++17+)

      • 如果使用 C++17 或以上版本,推荐使用 u8path() 处理 UTF-8 字符串。
    5. 避免直接将 std::filesystem::path 转换为 std::string

      • 直接使用 path().wstring()path().u8string() 来获取字符串。

    ✅ 最终建议

    如果你只是想遍历文件并统计总大小,建议使用 std::filesystem::pathwstring() 方法,而不是转换成 std::string。这样可以避免编码转换错误。

    如果你还有其他问题(例如文件读取、编码转换等),欢迎继续提问!

    评论

报告相同问题?

问题事件

  • 创建了问题 1月2日