在 C++17 标准中,std::filesystem 成为标准库的一部分,它为文件和目录的操作提供了统一、跨平台的接口。相比旧时的 dirent.h、windows.h 等平台特定头文件,std::filesystem 让文件系统相关的任务变得更直观、更安全。本文将介绍其核心功能、常见用法以及一些实用技巧,帮助你快速掌握这一现代工具。
1. 目录遍历(Directory Iteration)
使用 std::filesystem::directory_iterator 或 recursive_directory_iterator 可以轻松遍历目录树:
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
fs::path root = "./src";
for (const auto& entry : fs::recursive_directory_iterator(root)) {
std::cout << entry.path() << (entry.is_directory() ? " [DIR]" : "") << '\n';
}
}
- 递归遍历:
recursive_directory_iterator默认会递归进入子目录。 - 过滤:通过
entry.is_regular_file()、entry.is_directory()等判定文件类型,配合entry.path().extension()可以筛选特定后缀。
2. 路径操作(Path Manipulation)
std::filesystem::path 提供了面向对象的路径处理方式:
fs::path p = "/home/user/Documents/report.txt";
std::cout << "Filename: " << p.filename() << '\n'; // report.txt
std::cout << "Extension: " << p.extension() << '\n'; // .txt
std::cout << "Stem: " << p.stem() << '\n'; // report
std::cout << "Parent: " << p.parent_path() << '\n'; // /home/user/Documents
路径拼接使用 / 运算符,具有语义化且不易出错:
fs::path config = p.parent_path() / "config.json";
3. 文件与目录操作(File and Directory Operations)
| 操作 | 标准函数 | 说明 |
|---|---|---|
| 创建文件夹 | fs::create_directory / create_directories |
单层或多层递归创建 |
| 删除文件夹 | fs::remove_all |
递归删除 |
| 拷贝文件 | fs::copy |
支持覆盖、仅更新等选项 |
| 移动文件 | fs::rename |
原子移动(在同一文件系统内) |
| 读取文件属性 | fs::last_write_time、file_size |
获取修改时间、大小 |
示例:复制并覆盖文件
fs::copy(source, destination, fs::copy_options::overwrite_existing);
4. 异常与错误处理
所有 std::filesystem 函数在遇到错误时会抛出 std::filesystem::filesystem_error。可以捕获该异常查看错误码:
try {
fs::remove_all("nonexistent");
} catch (const fs::filesystem_error& e) {
std::cerr << "Error: " << e.what() << '\n';
std::cerr << "Path: " << e.path1() << '\n';
}
若想忽略错误,可以使用返回值检查或 std::error_code 版本:
std::error_code ec;
fs::remove_all("nonexistent", ec);
if (ec) {
std::cerr << "Failed to remove: " << ec.message() << '\n';
}
5. 性能与平台差异
- 跨平台:在 Windows、Linux、macOS 上行为基本一致,但路径分隔符不同。
std::filesystem::path会自动处理。 - 性能:在大量文件遍历时,
std::filesystem可能比boost::filesystem更快,因为它是 C++ 标准库的一部分,编译器优化更深。 - 符号链接:使用
fs::is_symlink判断,read_symlink获取目标路径。递归遍历时可通过options::follow_directory_symlink控制。
6. 常见陷阱
- 相对路径与绝对路径:若使用相对路径,最好先
canonical()或absolute(),避免路径不确定性。 - 大小写敏感:Windows 文件系统不区分大小写,Linux 区分。写代码时注意。
- Unicode 路径:Windows 需要
std::wstring路径,C++17 的std::filesystem已经支持 Unicode,确保编译器使用 Unicode 编码。
7. 小结
std::filesystem为 C++ 提供了强大的文件系统操作接口,统一了跨平台差异。- 通过
path、directory_iterator、file_size等工具,你可以快速完成文件遍历、复制、移动、删除等任务。 - 异常处理与错误码提供了灵活的错误管理方式。
掌握 std::filesystem 后,你的文件系统相关代码将变得更简洁、安全且可维护。试着将你项目中的文件操作迁移到 std::filesystem,体会它带来的便利吧!