Windows 不支持 dirent.h,需用 C++17 std::filesystem::directory_iterator 替代;它跨平台、自动处理路径与编码,且无需手动管理资源。

dirent.h 在 Windows 上根本不能用
直接告诉你:Windows 默认不带 dirent.h,VS、MinGW(非MSYS2环境)下编译会报错 fatal error: dirent.h: No such file or directory。这不是你路径没配对,是它压根不是 Windows 原生 API 的一部分。
常见错误现象:#include <dirent.h></dirent.h> 编译失败;或用了 MinGW-w64 但忘了加 -D__USE_MINGW_ANSI_STDIO 导致 readdir() 返回乱码文件名。
- Linux/macOS 可直接用,头文件和函数都标准
- Windows 下想用,得自己引入兼容层(如 tronkko/dirent),或改用
<filesystem></filesystem>(C++17 起) - MSVC 用户别挣扎——别试图找“Windows 版 dirent.h”,那是白费时间
std::filesystem::directory_iterator 是更靠谱的跨平台选择
C++17 引入的 std::filesystem 不仅能遍历目录,还自动处理路径分隔符、编码、符号链接等脏活。它不是“替代方案”,而是当前 C++ 的事实标准。
使用场景:需要跨平台、要过滤文件类型、要获取文件大小/最后修改时间、不想手动管理 DIR* 生命周期。
立即学习“C++免费学习笔记(深入)”;
#include <filesystem>
namespace fs = std::filesystem;
for (const auto& entry : fs::directory_iterator("/path/to/dir")) {
if (entry.is_regular_file()) {
std::cout << entry.path().filename() << "\n";
}
}
- 注意:GCC 需加编译选项
-lstdc++fs(GCC -
directory_iterator不递归,要递归请用recursive_directory_iterator - 路径字符串建议用
fs::path构造,避免裸字符串拼接导致反斜杠转义问题
readdir() 的三个关键陷阱(Linux/macOS 下真要用)
如果你明确在 Linux/macOS 上写服务、嵌入式工具,或必须对接旧代码,readdir() 还是得懂。但它比看起来危险得多。
常见错误现象:程序随机崩溃、漏读文件、中文文件名显示为 ????、readdir() 返回 NULL 后继续解引用。
-
struct dirent*指针由readdir()内部复用,每次调用都会覆盖前次内容,不能存指针、不能跨循环迭代保存 - 文件名字段
d_name是 char 数组,长度固定(NAME_MAX),超长名会被截断,且不保证以\0结尾(需手动检查) - 返回值为
NULL表示结束或出错,必须用errno判断:若errno == 0才是正常结束;否则可能是权限不足或 I/O 错误
性能差异:filesystem vs readdir vs system("ls")
别图省事用 system("ls") 解析输出——慢、不可靠、有 shell 注入风险,且无法获取文件元信息。
真实性能排序(同等条件下):readdir() ≈ std::filesystem::directory_iterator > system("ls")。前者都是系统调用直通,后者要 fork + exec + pipe + 字符串解析。
-
readdir()最轻量,但需手动处理编码、过滤、stat -
std::filesystem在首次构造时可能多一次stat()(取决于实现),但后续entry.is_regular_file()等操作基本零开销(缓存了 d_type 或 stat 结果) - 如果只想要文件名列表且不做任何判断,
readdir()确实略快,但差不了几个微秒——够不到性能瓶颈级别
dirent.h,结果 CI 在 Windows 上直接挂;或者以为 std::filesystem “只是语法糖”,没意识到它背后是不同 OS 的原生 API 封装,路径行为、错误码、编码处理全都不一样。








