std::filesystem 是当前 C++ 获取文件夹下所有文件名最可靠、跨平台的方式;dirent.h 仅限类 Unix 系统,Windows 下需额外兼容处理,不推荐新项目使用。

用 std::filesystem 是当前 C++ 获取文件夹下所有文件名最可靠、跨平台的方式;dirent.h 仅限类 Unix 系统,Windows 下需额外兼容处理,不推荐新项目使用。
std::filesystem::directory_iterator 遍历目录(C++17 起)
这是标准、简洁、类型安全的做法。注意必须开启 C++17 或更高标准,且链接 stdc++fs(GCC)或确保 MSVC 版本支持(VS2019 v16.8+ 默认支持)。
常见错误现象:undefined reference to 'std::filesystem::directory_iterator::directory_iterator' —— 忘加链接选项;std::filesystem::directory_iterator 构造失败抛 std::filesystem::filesystem_error —— 路径不存在、无权限或不是目录。
- 用
std::filesystem::is_regular_file()过滤掉子目录(如只需文件名,不含子文件夹) - 用
entry.path().filename().string()提取纯文件名(不含路径) - 若需递归遍历,请改用
std::filesystem::recursive_directory_iterator - 路径字符串建议用
std::filesystem::path构造,避免手动拼接斜杠(/vs)
#include <filesystem>
#include <iostream>
#include <vector>
<p>namespace fs = std::filesystem;</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/6e7abc4abb9f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">C++免费学习笔记(深入)</a>”;</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/gongju/2823" title="C++14">C++14</a>
<p>C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p>int main() {
std::vector<std::string> filenames;
try {
for (const auto& entry : fs::directory_iterator("data/")) {
if (fs::is_regular_file(entry)) {
filenames.push_back(entry.path().filename().string());
}
}
} catch (const fs::filesystem_error& e) {
std::cerr << "fs error: " << e.what() << '
';
}
}
dirent.h 在 Linux/macOS 上的典型用法(非标准,不可跨平台)
dirent.h 是 POSIX 接口,Windows 原生不提供;MinGW 可模拟,但 MSVC 完全不支持(除非引入第三方头或改用 _findfirst)。它轻量但无类型检查,容易漏掉 . 和 .. 目录项。
常见错误现象:readdir() returns NULL but no error set —— 忘记检查 errno;DT_DIR 判断在某些旧系统上不可靠;未跳过 . 和 .. 导致逻辑异常。
- 必须包含
<dirent.h></dirent.h>和<sys></sys>(如需判断类型) - 用
stat()+S_ISREG()判断是否为普通文件(d_type字段在某些文件系统中不可靠) - 显式跳过
entry->d_name[0] == '.'的条目(包括.和..) - 记得调用
closedir(),否则资源泄漏
#include <dirent.h>
#include <sys/stat.h>
#include <vector>
#include <string>
<p>std::vector<std::string> list_files_c(const char<em> path) {
std::vector<std::string> names;
DIR</em> dir = opendir(path);
if (!dir) return names;</p><pre class="brush:php;toolbar:false;">struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
if (entry->d_name[0] == '.') continue; // skip . and ..
std::string fullpath = std::string(path) + "/" + entry->d_name;
struct stat st;
if (stat(fullpath.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
names.push_back(entry->d_name);
}
}
closedir(dir);
return names;}
Windows 下用 _findfirst/_findnext(仅 MSVC/MinGW 兼容)
这是 Windows 传统做法,比 dirent.h 更“原生”,但完全不可移植。结构体字段名(如 _finddata_t.name)和通配符语法(*.*)是硬编码习惯,容易写错。
常见错误现象:_findfirst 返回 -1 但没检查 errno;忘记用 _findclose();误把 _A_SUBDIR 当作文件类型标志(它只是属性位,需与 _A_NORMAL 组合判断)。
- 搜索模式必须含通配符,例如
"data\*",不能只写"data" - 用
file.attrib & _A_SUBDIR判断是否为目录,而非直接比较file.attrib == _A_SUBDIR -
_findfirst返回句柄,后续必须配对_findnext+_findclose - 文件名字段是
file.name,不是file.filename
#include <io.h>
#include <vector>
#include <string>
<p>std::vector<std::string> list_files_win(const char<em> path) {
std::vector<std::string> names;
std::string pattern = std::string(path) + "</em>";
_finddata_t file;
intptr_t hFile = _findfirst(pattern.c_str(), &file);
if (hFile == -1) return names;</p><pre class="brush:php;toolbar:false;">do {
if (!(file.attrib & _A_SUBDIR)) { // not a directory
names.push_back(file.name);
}
} while (_findnext(hFile, &file) == 0);
_findclose(hFile);
return names;}
真正要注意的是:std::filesystem 的路径对象在构造时会做规范化(如合并 ../),而 dirent.h 和 _findfirst 返回的都是原始目录项名称,不做路径解析。如果你依赖文件名顺序,std::filesystem::directory_iterator 不保证排序,需要手动 std::sort;而 readdir 和 _findnext 的顺序取决于文件系统底层,也不应假设有序。

















