C++遍历打印文件夹及子文件夹特殊字符文件抛异常如何解决
问题根因
当前代码崩溃有两个核心触发点:
std::filesystem::recursive_directory_iterator默认构造时,遇到无权限访问的目录、损坏的符号链接、系统保留名文件时会直接抛出std::filesystem::filesystem_error异常,未捕获时会直接终止程序- 直接向
std::cout传入directory_entry/path对象时,会做隐式窄字符转换,遇到中文、带变音符号的非ASCII字符时,在Windows默认GBK/系统ANSI编码环境下会触发转换异常,同时控制台编码不匹配也会导致输出失败抛错
最简修复方案
不需要引入第三方库,直接调整迭代器参数+适配输出逻辑即可,步骤如下:
- 构造递归迭代器时传入跳过权限错误的选项,同时绑定
std::error_code捕获遍历过程的所有非致命错误,避免遍历中途抛异常终止 - 输出路径时不要直接输出
dir_entry对象,根据平台选择对应原生字符串格式输出,避免字符编码转换异常 - Windows环境下提前设置控制台输入输出编码为UTF-8,匹配文件系统的Unicode路径编码
修复后可直接运行的代码
#include <filesystem> #include <iostream> #include <system_error> #ifdef _WIN32 #include <windows.h> #endif namespace fs = std::filesystem; void printAllInPath(fs::path a) { std::error_code ec; // 构造迭代器时传入跳过权限拒绝选项,绑定错误码,不抛异常 fs::recursive_directory_iterator it(a, fs::directory_options::skip_permission_denied, ec); if (ec) { std::cerr << "打开目标路径失败: " << ec.message() << "\n"; return; } for (const auto& dir_entry : it) { // 遇到单个文件错误直接清空错误码跳过,不中断整体遍历 if (ec) { ec.clear(); continue; } const fs::path& entry_path = dir_entry.path(ec); if (ec) continue; #ifdef _WIN32 // Windows下用宽字符输出,匹配系统原生Unicode路径格式 std::wcout << entry_path.wstring() << L"\n"; #else // Unix/Linux/macOS下直接输出UTF-8窄字符串 std::cout << entry_path.string() << "\n"; #endif } } int main(int argc, char* argv[]) { #ifdef _WIN32 // Windows下设置控制台编码为UTF-8,适配非ASCII字符输出 SetConsoleOutputCP(CP_UTF8); SetConsoleCP(CP_UTF8); #endif // 调用示例:传入要遍历的路径即可 if (argc > 1) { printAllInPath(argv[1]); } return 0; }
补充说明
- 上述代码已经可以覆盖所有非ASCII文件名、特殊符号文件名的遍历场景,遇到无权限文件、损坏链接会自动跳过不会崩溃
- 如果需要区分文件/文件夹,可以在循环内加
dir_entry.is_directory(ec)、dir_entry.is_regular_file(ec)判断,所有filesystem接口传入std::error_code参数就不会抛出异常 - 不要使用隐式的path到string的转换,所有路径字符串获取都显式调用对应平台的接口,避免编码转换触发异常
内容的提问来源于stack exchange,提问作者Anton C
相关产品推荐
相关产品推荐

