C++ 进阶(21):文件系统——filesystem 库、路径操作、目录遍历
更新时间:2026-09-01。本文是
languages/cpp/intermediate/进阶第 21 篇,接 chrono 时间库。C++17 引入了<filesystem>,标准库终于有了跨平台的文件系统操作。路径操作、目录遍历、文件信息查询,不用再依赖std::filesystem或系统 API。
本文要回答的问题
- path 类怎么用?路径拼接、分解、规范化?
- 目录遍历怎么做?递归遍历和非递归遍历?
- 文件信息查询(大小、修改时间、权限)怎么用?
- 错误处理:filesystem_error 和 error_code 两种方式?
一、path:路径操作
cpp
#include <filesystem>
namespace fs = std::filesystem;
// 路径拼接
fs::path p = "dir" / "sub" / "file.txt";
// 跨平台:Windows 上用 \,Linux 上用 /
// 路径分解
p.root_name(); // "C:"(Windows)或 ""(Linux)
p.root_directory();// "/"
p.parent_path(); // "dir/sub"
p.filename(); // "file.txt"
p.stem(); // "file"
p.extension(); // ".txt"
// 路径规范化
fs::path p2 = fs::path("a/../b/c"); // 不规范化
fs::path p3 = p2.lexically_normal(); // "b/c"
// 判断
p.is_absolute(); // 是否绝对路径
p.is_relative(); // 是否相对路径二、文件信息查询
cpp
fs::path p = "test.txt";
// 文件是否存在
bool exists = fs::exists(p);
// 文件类型
fs::is_regular_file(p); // 普通文件
fs::is_directory(p); // 目录
fs::is_symlink(p); // 符号链接
// 文件信息
auto info = fs::status(p);
auto perms = info.permissions();
// 常用信息
auto size = fs::file_size(p); // 文件大小
auto mtime = fs::last_write_time(p); // 修改时间
auto space = fs::space(p); // 磁盘空间三、目录遍历
cpp
// 非递归遍历(只读一层)
for (auto& entry : fs::directory_iterator(".")) {
cout << entry.path() << "\n";
}
// 递归遍历
for (auto& entry : fs::recursive_directory_iterator(".")) {
if (entry.is_regular_file()) {
cout << entry.path() << ": " << entry.file_size() << " bytes\n";
}
}
// 控制递归深度
fs::recursive_directory_iterator it(".",
fs::directory_options::skip_permission_denied);
it.disable_recursion_pending(); // 跳过当前目录的子目录四、文件操作
cpp
// 复制
fs::copy("src.txt", "dst.txt");
fs::copy("src_dir", "dst_dir", fs::copy_options::recursive);
// 移动/重命名
fs::rename("old.txt", "new.txt");
// 删除
fs::remove("file.txt"); // 删除文件
fs::remove_all("dir"); // 递归删除目录
// 创建
fs::create_directory("dir");
fs::create_directories("a/b/c"); // 递归创建
// 临时文件
auto tmp = fs::temp_directory_path() / "myapp-XXXXXX";五、错误处理
cpp
// 方式 1:异常
try {
auto size = fs::file_size("nonexist.txt");
} catch (const fs::filesystem_error& e) {
cout << e.what() << "\n";
cout << e.path1() << "\n"; // 第一个路径
cout << e.path2() << "\n"; // 第二个路径(如果有)
}
// 方式 2:error_code(推荐,无异常开销)
std::error_code ec;
auto size = fs::file_size("nonexist.txt", ec);
if (ec) {
cout << ec.message() << "\n"; // "No such file or directory"
}六、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
路径拼接用 + | 路径丢失分隔符 | 用 operator/ 或 path::append |
| 不检查错误就用 | 文件不存在抛出异常 | 用 error_code 版本 |
| 递归遍历大量文件 | 性能慢 | 用非递归 + 自己管理栈 |
| 删除目录用 remove | 非空目录删不掉 | 用 remove_all |
相关与延伸
下一篇:格式化库——format 深入;C 的文件操作对比,见 C 文件 I/O。
一句话总结
C++ filesystem 库:path 类用 operator/ 拼接路径,跨平台自动处理分隔符;directory_iterator 非递归遍历,recursive_directory_iterator 递归遍历;fs::exists 判断存在,fs::file_size 大小,fs::last_write_time 修改时间;错误处理建议用 error_code 版本避免异常开销;copy_options::recursive 递归复制,remove_all 递归删除。