随着 C++17 的发布,标准库新增了一个强大的文件系统库——std::filesystem。它提供了对文件与目录的创建、删除、遍历、属性查询等操作的统一接口,极大地方便了跨平台的文件处理工作。本文将从基础使用入手,演示常见操作,并结合实际案例展示如何使用该库完成一个简易的文件备份工具。
1. 头文件与命名空间
#include <filesystem>
namespace fs = std::filesystem;
- `#include `:引入文件系统相关类型与函数。
namespace fs = std::filesystem;:为简化代码,常用的做法是使用别名fs。
注意:在 GCC 8 之前的版本,
std::filesystem处于实验性质,需加-std=gnu++17并链接-lstdc++fs。在较新编译器(GCC 9+、Clang 10+、MSVC 19.20+)已稳定。
2. 基础操作
2.1 检查路径是否存在
fs::path p = "/usr/local/bin";
if (fs::exists(p)) {
std::cout << p << " exists.\n";
}
2.2 判断文件或目录
if (fs::is_regular_file(p)) // 普通文件
if (fs::is_directory(p)) // 目录
2.3 创建目录
fs::path dir = "logs";
fs::create_directory(dir); // 只创建单层目录
fs::create_directories(dir / "2026"); // 递归创建多层目录
2.4 读取目录
for (const auto &entry : fs::directory_iterator(dir)) {
std::cout << entry.path() << '\n';
}
2.5 复制、移动、删除
fs::copy_file(src, dst, fs::copy_options::overwrite_existing);
fs::rename(src, dst);
fs::remove_all(dir); // 删除目录及其内容
3. 读取文件属性
auto ftime = fs::last_write_time(p);
auto sz = fs::file_size(p);
last_write_time 返回一个 file_time_type,可以使用 std::chrono 进行转换。
4. 实战案例:简易文件备份工具
下面给出一个完整示例,演示如何使用 std::filesystem 复制源目录下的所有文件到目标备份目录,且只复制最近修改时间超过一天的文件。
#include <filesystem>
#include <iostream>
#include <chrono>
namespace fs = std::filesystem;
// 判断文件是否超过阈值(单位:天)
bool isModifiedAfter(const fs::path& p, int days) {
auto ftime = fs::last_write_time(p);
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
ftime - fs::file_time_type::clock::now() + std::chrono::system_clock::now()
);
auto now = std::chrono::system_clock::now();
return (now - sctp) > std::chrono::hours(24 * days);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: backup <source_dir> <backup_dir>\n";
return 1;
}
fs::path srcDir = argv[1];
fs::path dstDir = argv[2];
if (!fs::exists(srcDir) || !fs::is_directory(srcDir)) {
std::cerr << "Source directory does not exist.\n";
return 1;
}
fs::create_directories(dstDir); // 确保目标目录存在
for (auto& entry : fs::recursive_directory_iterator(srcDir)) {
if (fs::is_regular_file(entry.path())) {
if (isModifiedAfter(entry.path(), 1)) {
fs::path relative = fs::relative(entry.path(), srcDir);
fs::path dest = dstDir / relative;
fs::create_directories(dest.parent_path()); // 递归创建子目录
fs::copy_file(entry.path(), dest, fs::copy_options::overwrite_existing);
std::cout << "Backed up: " << entry.path() << " -> " << dest << '\n';
}
}
}
std::cout << "Backup completed.\n";
return 0;
}
说明
- 递归遍历:
fs::recursive_directory_iterator能遍历子目录。 - 相对路径:
fs::relative计算源文件相对源根目录的路径,保证备份目录结构一致。 - 日期判断:
isModifiedAfter将文件时间转换为系统时间,计算与当前时间差。 - 创建子目录:在复制前确保目标子目录已存在。
5. 性能与跨平台注意事项
- 性能:
std::filesystem在 I/O 密集型操作中与传统boost::filesystem相比,性能相当甚至略有提升。 - Unicode:Windows 的
std::filesystem::path在 UTF‑8 代码页下默认使用 UTF‑16 内部表示,读取时会自动转换。 - 错误处理:使用
std::error_code或try-catch捕获异常。示例中使用默认异常模式,若不想抛异常可使用fs::remove_all(p, ec)之类的 API。
6. 结语
std::filesystem 为 C++ 提供了现代、跨平台的文件操作方式,减少了繁琐的系统调用与第三方库。只要掌握了它的基本使用,几乎可以覆盖日常开发中所有的文件与目录处理需求。希望本文能帮助你在项目中快速上手,提升开发效率。