在 C++17 标准中, 库被正式引入,提供了一套统一、跨平台的文件系统操作接口。相比传统的 POSIX 或 Windows API,std::filesystem 的语义更清晰、错误处理更方便。下面我们以一个简单的文件遍历与复制示例来演示其使用方法。
1. 环境准备
# 编译示例(假设使用 g++)
g++ -std=c++17 -Wall -Wextra -O2 -pthread main.cpp -o fs_demo
注意:部分旧编译器(如 GCC 7.x)需要加上
-lstdc++fs链接库,现代编译器(如 GCC 9+、Clang 10+)已默认开启。
2. 基础 API
| 函数 | 说明 | 备注 |
|---|---|---|
std::filesystem::exists(const path&) |
判断路径是否存在 | 返回 true/false |
std::filesystem::is_directory(const path&) |
判断是否为目录 | |
std::filesystem::create_directories(const path&) |
创建多级目录 | |
std::filesystem::copy(const path&, const path&, copy_options) |
复制文件/目录 | copy_options 可自定义行为 |
std::filesystem::directory_iterator / recursive_directory_iterator |
遍历目录 | 前者一次级别,后者递归 |
3. 代码实例
#include <iostream>
#include <filesystem>
#include <system_error>
namespace fs = std::filesystem;
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: fs_demo <source_dir> <dest_dir>\n";
return 1;
}
fs::path src(argv[1]);
fs::path dst(argv[2]);
// 1. 验证源目录
if (!fs::exists(src) || !fs::is_directory(src)) {
std::cerr << "Source directory does not exist or is not a directory.\n";
return 1;
}
// 2. 创建目标目录(若不存在)
std::error_code ec;
fs::create_directories(dst, ec);
if (ec) {
std::cerr << "Failed to create destination: " << ec.message() << '\n';
return 1;
}
// 3. 递归复制
for (const auto& entry : fs::recursive_directory_iterator(src)) {
const auto& path = entry.path();
auto relative = fs::relative(path, src);
auto target = dst / relative;
if (entry.is_directory()) {
fs::create_directories(target, ec);
if (ec) {
std::cerr << "Error creating directory " << target << ": " << ec.message() << '\n';
continue;
}
} else if (entry.is_regular_file()) {
fs::copy(path, target, fs::copy_options::overwrite_existing, ec);
if (ec) {
std::cerr << "Error copying file " << path << " to " << target << ": " << ec.message() << '\n';
continue;
}
}
}
std::cout << "Copy completed successfully.\n";
return 0;
}
关键点说明
-
错误处理
- 使用
std::error_code捕获非异常错误。std::filesystem也支持抛出std::filesystem::filesystem_error,但显式捕获error_code更可控。
- 使用
-
相对路径
fs::relative(path, src)用来计算目标目录下相对路径,保证复制结构保持一致。
-
复制选项
fs::copy_options::overwrite_existing表示目标文件已存在时覆盖。其他选项如skip_existing、update_existing等可根据需求使用。
-
递归遍历
recursive_directory_iterator会自动进入子目录并遍历所有文件和子文件夹。若只需要一次级别,可改用directory_iterator。
4. 常见错误与排查
| 错误 | 原因 | 解决方案 |
|---|---|---|
fs::relative 抛异常 |
源路径不在目标树上 | 确认 src 与 dst 的关系 |
复制时出现 Permission denied |
权限不足 | 以管理员或 root 权限运行,或修改文件权限 |
| 目标路径为空 | 传递错误参数 | 检查命令行输入 |
5. 进一步阅读
- C++20 版本的 ` ` 支持 `std::filesystem::file_time_type` 的高精度时间戳。
- 结合
std::filesystem::file_status与fs::file_type可实现更细粒度的文件属性检查。 - 在大型项目中,可封装一个
FileManager类,统一处理错误、日志、异步复制等需求。
使用 std::filesystem,你就可以用几行现代 C++ 代码完成复杂的文件操作,既安全又高效。祝编码愉快!