在 C++17 标准中, 库被正式引入,为跨平台的文件系统交互提供了统一且强大的 API。本文将从最常见的路径处理、文件读写,到递归遍历、权限检查等方面展开,帮助你快速掌握 std::filesystem 的使用技巧,并结合实际示例让你在项目中能直接上手。
1. 引入与编译
#include <filesystem>
namespace fs = std::filesystem;
在大多数编译器(gcc 8+、clang 7+、MSVC 2017+)中,只需链接 -lstdc++fs(gcc 8 以前需要),或直接编译即可。
g++ -std=c++17 -Wall -Wextra main.cpp -lstdc++fs
2. 路径(path)操作
2.1 基本构造
fs::path p1 = "C:/Users/John";
fs::path p2 = "/usr/local/bin";
fs::path p3 = fs::path("foo") / "bar" / "baz.txt"; // 组合路径
fs::path 自动识别平台分隔符,内部使用 std::string 存储。
2.2 访问路径属性
std::cout << "Full path: " << p3 << '\n'; // 输出完整路径
std::cout << "Parent: " << p3.parent_path() << '\n'; // 上级目录
std::cout << "Filename: " << p3.filename() << '\n'; // 文件名
std::cout << "Extension: "<< p3.extension() << '\n'; // 扩展名
2.3 路径比较与相对化
fs::path a = "/home/user/project/src";
fs::path b = "/home/user/project/docs";
auto rel = fs::relative(a, b); // 生成相对路径
// 结果:../src
注意:
fs::relative只在两个路径共享同一根时才有意义,否则抛出std::invalid_argument。
3. 文件与目录的基本操作
3.1 创建与删除
fs::create_directory("/tmp/hello"); // 单级目录
fs::create_directories("/tmp/hello/world"); // 多级目录
fs::remove("/tmp/hello/world"); // 删除文件或空目录
fs::remove_all("/tmp/hello"); // 删除非空目录
3.2 复制与移动
fs::copy("/tmp/hello/world/file.txt", "/tmp/copy.txt",
fs::copy_options::overwrite_existing);
fs::rename("/tmp/old.txt", "/tmp/new.txt");
3.3 文件信息
fs::file_size("/etc/passwd"); // 文件大小
fs::last_write_time("/etc/passwd"); // 最后修改时间
last_write_time返回std::filesystem::file_time_type,可通过std::chrono转为可读时间。
4. 迭代器(Directory Iteration)
4.1 简单遍历
for (const auto& entry : fs::directory_iterator("/tmp/hello")) {
std::cout << entry.path() << '\n';
}
4.2 递归遍历
for (const auto& entry : fs::recursive_directory_iterator("/tmp/hello")) {
if (entry.is_regular_file()) {
std::cout << "File: " << entry.path() << '\n';
} else if (entry.is_directory()) {
std::cout << "Dir : " << entry.path() << '\n';
}
}
recursive_directory_iterator默认会跟随符号链接,若不想跟随可使用fs::directory_options::follow_directory_symlink。
4.3 排序与过滤
std::vector<fs::directory_entry> files;
for (const auto& entry : fs::directory_iterator("/tmp/hello")) {
if (entry.is_regular_file() && entry.path().extension() == ".txt") {
files.push_back(entry);
}
}
std::sort(files.begin(), files.end(),
[](auto& a, auto& b){ return a.path() < b.path(); });
for (auto& e : files) std::cout << e.path() << '\n';
5. 文件内容的读取与写入
虽然 std::filesystem 主要关注路径与元数据,实际文件 I/O 仍使用传统 `