在C++17标准中,<filesystem>头文件提供了一套统一且强大的文件系统接口,使得文件与目录的创建、删除、遍历、属性查询等操作变得极为简洁。本文将演示如何使用 std::filesystem 进行常见的文件操作,并给出完整的代码示例。
1. 准备工作
- 编译器需要支持C++17,例如 GCC 8+、Clang 7+、MSVC 2017+。
- 需要在编译时链接
stdc++fs(GCC 8之前的版本)。
g++ -std=c++17 -Wall -Wextra -O2 -pthread main.cpp -lstdc++fs
2. 常用操作
| 操作 | 关键函数 | 示例 |
|---|---|---|
| 创建目录 | std::filesystem::create_directory 或 create_directories |
fs::create_directories("data/logs"); |
| 删除文件 | std::filesystem::remove |
fs::remove("temp.txt"); |
| 删除目录(含子目录) | std::filesystem::remove_all |
fs::remove_all("data"); |
| 判断是否为文件/目录 | is_regular_file、is_directory |
if(fs::is_regular_file(p)) { ... } |
| 遍历目录 | fs::directory_iterator 或 recursive_directory_iterator |
for(auto& entry : fs::recursive_directory_iterator(".")) { ... } |
| 复制文件 | fs::copy |
fs::copy("src.txt", "dst.txt", fs::copy_options::overwrite_existing); |
| 移动/重命名文件 | fs::rename |
fs::rename("old.txt", "new.txt"); |
| 查询文件大小 | file_size |
auto sz = fs::file_size("data.txt"); |
| 获取文件修改时间 | last_write_time |
auto t = fs::last_write_time("data.txt"); |
3. 示例代码
下面的程序演示了从创建目录到遍历目录、复制文件、删除等完整流程。
#include <iostream>
#include <filesystem>
#include <chrono>
#include <iomanip>
namespace fs = std::filesystem;
// 打印文件或目录的基本信息
void print_info(const fs::path& p) {
std::cout << "Path: " << p << '\n';
std::cout << "Is dir: " << fs::is_directory(p) << '\n';
std::cout << "Is regular: " << fs::is_regular_file(p) << '\n';
std::cout << "Size: ";
if (fs::is_regular_file(p)) std::cout << fs::file_size(p) << " bytes\n";
else std::cout << "N/A\n";
auto t = fs::last_write_time(p);
auto s = std::chrono::time_point_cast<std::chrono::system_clock::duration>(t - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
std::cout << "Modified: " << std::put_time(std::localtime(&std::chrono::system_clock::to_time_t(s)), "%F %T") << "\n";
std::cout << "---------------------------------\n";
}
int main() {
// 1. 创建目录
fs::create_directories("demo/logs");
std::cout << "创建目录完成。\n";
// 2. 写一个测试文件
std::ofstream("demo/test.txt") << "Hello, filesystem!\n";
std::cout << "写文件完成。\n";
// 3. 复制文件
fs::copy("demo/test.txt", "demo/logs/test_copy.txt", fs::copy_options::overwrite_existing);
std::cout << "文件复制完成。\n";
// 4. 遍历 demo 目录
std::cout << "遍历 demo 目录:\n";
for (auto& entry : fs::recursive_directory_iterator("demo")) {
print_info(entry.path());
}
// 5. 重命名文件
fs::rename("demo/logs/test_copy.txt", "demo/logs/test_renamed.txt");
std::cout << "文件重命名完成。\n";
// 6. 删除单个文件
fs::remove("demo/test.txt");
std::cout << "删除 test.txt 完成。\n";
// 7. 删除整个 demo 目录
fs::remove_all("demo");
std::cout << "删除 demo 目录完成。\n";
return 0;
}
4. 小技巧
- 错误处理:
std::filesystem的大部分函数会抛出std::filesystem::filesystem_error。使用try/catch或者error_code参数可以优雅地处理异常。 - 跨平台:
std::filesystem兼容 Windows、Linux、macOS。注意 Windows 需要使用\\或者R"(path)"原始字符串。 - 性能:对于大文件目录遍历,建议使用
fs::directory_options::skip_permission_denied来跳过无权限的路径,以避免阻塞。
5. 结语
C++17 的 `
` 标准化了文件系统操作,减少了平台差异和繁琐的系统调用。掌握它后,你可以在 C++ 项目中更专注于业务逻辑,而不必为文件操作的细节头疼。祝你编码愉快!