C++17 std::filesystem 入门与概念
为何在现代 C++ 项目中使用 std::filesystem
在 C++17 标准中,std::filesystem 提供了一组跨平台的文件系统操作接口,帮助开发者统一处理路径、遍历目录、创建或删除文件等能力。跨平台一致性是其最大的优势之一。
核心对象是 std::filesystem::path,它可以表示相对路径和绝对路径,并支持与字符串的互操作,提供了丰富的成员函数用于拼接、提取和规范化路径。
// 了解 path 的基本用法
#include
#include
namespace fs = std::filesystem;int main() {fs::path p = "logs/app.log";std::cout << "路径:" << p << std::endl;std::cout << "父级路径:" << p.parent_path() << std::endl;return 0;
}
快速起步:包含头文件、命名空间与基础操作
包含头文件与创建命名空间别名
首先添加头文件 <filesystem>,并在代码中使用 命名空间别名 以简化书写。
常见起步写法是 namespace fs = std::filesystem;,之后即可使用 fs::path 和其它 API。
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;int main() {fs::path p = "/var/log";std::cout << p << std::endl;return 0;
}
常用操作:路径与状态检查
路径存在性与类型判断
要判断路径是否存在,可以使用 fs::exists;要判断类型,可以组合使用 fs::is_regular_file、fs::is_directory。
错误处理也可以通过返回值与 std::error_code 或异常进行判断,提供了两种安全的错误处理路径。
#include <filesystem>
#include <iostream>
#include <system_error>
namespace fs = std::filesystem;int main() {fs::path p = "docs/report.txt";if (fs::exists(p)) {std::cout << p << " exists" << std::endl;if (fs::is_regular_file(p)) {std::cout << "是普通文件" << std::endl;}}return 0;
}
遍历目录:遍历、过滤与迭代器
使用目录遍历迭代器
遍历目录最直接的方法是 directory_iterator,它逐条枚举目录项并可通过 path() 访问子项路径,适合简单遍历。
对于递归遍历,可以使用 recursive_directory_iterator,它会遍历子目录及其子目录,常用于统计、搜索等场景。
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;int main() {for (const auto & entry : fs::directory_iterator("/tmp")) {std::cout << entry.path() << std::endl;}for (const auto & entry : fs::recursive_directory_iterator("/tmp")) {if (entry.is_regular_file()) {std::cout << entry.path() << std::endl;}}return 0;
}
文件创建与删除:复制、重命名、删除
创建目录与文件、以及删除操作
使用 fs::create_directory 或 fs::create_directories 来创建目录;创建文件通常通过写入操作实现,库本身提供了对路径的支持。
删除操作包括 fs::remove 与 fs::remove_all,前者仅删除单个文件或空目录,后者会递归删除目录及其内容。
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;int main() {fs::path dir = "data/new_dir";if (fs::create_directories(dir)) {std::ofstream file((dir / "hello.txt").string());file << "hello";file.close();}// 删除操作示例fs::remove(dir / "hello.txt");fs::remove_all("data");return 0;
}
错误处理与异常安全
异常 vs 错误码(error_code)
std::filesystem 的大多数操作在异常模式下会抛出 std::filesystem::filesystem_error,也可以通过返回值与 std::error_code 或使用无抛出版本来处理错误。

在性能敏感的场景下,优先考虑带有 std::error_code 的版本,以避免异常带来的开销,同时也能清晰地获得错误信息。
#include <filesystem>
#include <system_error>
#include <iostream>
namespace fs = std::filesystem;int main() {std::error_code ec;if (!fs::exists("unknown.txt", ec)) {std::cerr << "错误:" << ec.message() << std::endl;}return 0;
}
跨平台注意事项与性能
跨平台差异与性能优化要点
虽然 std::filesystem 提供跨平台接口,但不同平台对路径分隔符、权限模型等仍有差异,开发时需要通过测试来确保行为一致性。
为了提升性能,尽量减少磁盘 I/O 的重复访问,例如将多次 exists 调用合并为一次结果缓存,并使用对等的 path 操作来避免不必要的 I/O。
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;int main() {fs::path root = "/opt/app";if (fs::exists(root)) {std::cout << "Root exists" << std::endl;}return 0;
}


