在 C++17 标准中, 库首次被正式加入标准库,彻底改变了 C++ 程序员在文件和目录操作上的体验。与早期的 Boost.Filesystem 相比,标准库的实现更加轻量、跨平台且语义更明确。下面,我们将从基本使用、路径操作、文件信息查询、文件系统遍历、异常处理以及 C++20 的改进等方面,系统性地介绍 std::filesystem 的核心功能与最佳实践。
1. 目录与文件路径的统一处理
1.1 路径对象 std::filesystem::path
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
fs::path p = "/usr/local/bin";
std::cout << "Path string: " << p.string() << '\n';
std::cout << "File extension: " << p.extension() << '\n';
}
path 对象是路径的核心封装,提供了 string(), native(), generic_string() 等方法。extension() 返回文件扩展名,stem() 返回文件名去扩展名的部分,parent_path() 则返回父目录。
1.2 路径拼接与相对路径
fs::path base = "/home/user";
fs::path relative = "documents/report.txt";
fs::path full = base / relative; // 生成 /home/user/documents/report.txt
/ 运算符在路径拼接时会自动处理斜杠,避免手动拼接可能导致的错误。
2. 文件与目录操作
2.1 创建、删除、移动
fs::create_directory("test_dir"); // 创建单层目录
fs::create_directories("a/b/c"); // 创建多层目录
fs::remove("test_dir"); // 删除空目录
fs::remove_all("a"); // 删除目录及其所有内容
fs::rename("old.txt", "new.txt"); // 重命名或移动文件
2.2 读取文件信息
fs::file_status status = fs::status("example.txt");
if (fs::is_regular_file(status)) {
std::cout << "Size: " << fs::file_size("example.txt") << " bytes\n";
}
2.3 权限与属性
fs::permissions("example.txt", fs::perms::owner_write);
3. 遍历文件系统
3.1 递归遍历
for (const auto& entry : fs::recursive_directory_iterator("src")) {
std::cout << entry.path() << '\n';
}
默认递归会忽略符号链接,使用 fs::directory_options::follow_directory_symlink 可更改行为。
3.2 筛选文件
for (const auto& entry : fs::directory_iterator("src")) {
if (entry.path().extension() == ".cpp") {
std::cout << entry.path() << '\n';
}
}
4. 异常与错误码
`
` 支持两种错误处理方式:异常和错误码。默认情况下,操作失败会抛出 `std::filesystem::filesystem_error`。 “`cpp try { fs::create_directory(“/root/protected”); } catch (const fs::filesystem_error& e) { std::cerr ` 做了细粒度的错误码改进,支持 `std::error_code` 的返回值更丰富。 – C++23 引入 `fs::copy_options::skip_existing` 与 `fs::copy_options::overwrite_existing` 等复制选项,提升文件复制的灵活性。 – 通过 `fs::file_time_type` 可以获得文件的最后修改时间,支持更细致的时间比较。 ## 7. 实战示例:备份工具 下面给出一个简易备份程序示例,演示如何将源目录中所有 `.cpp` 文件复制到备份目录,保持目录结构。 “`cpp #include #include namespace fs = std::filesystem; void backup_cpp_files(const fs::path& src, const fs::path& dst) { std::error_code ec; for (const auto& entry : fs::recursive_directory_iterator(src, ec)) { if (entry.is_regular_file() && entry.path().extension() == “.cpp”) { fs::path relative = fs::relative(entry.path(), src, ec); fs::path target = dst / relative; fs::create_directories(target.parent_path(), ec); fs::copy_file(entry.path(), target, fs::copy_options::overwrite_existing, ec); if (ec) { std::cerr