在C++17标准发布后,标准库新增了std::filesystem模块,为文件与目录的操作提供了统一、跨平台的接口。相比传统的POSIX或Windows API,std::filesystem不再需要手工处理路径分隔符、错误码等细节,极大简化了文件系统编程。本文将通过几个典型场景,演示如何利用该库完成常见任务,并给出一些实用技巧。
1. 基础使用
首先需要包含头文件:
#include <filesystem>
namespace fs = std::filesystem;
使用前请确保编译器支持C++17,并链接对应的标准库(如g++:-lstdc++fs 在部分版本中需要)。
1.1 创建目录
fs::create_directories("/tmp/example/subdir");
create_directories 会递归创建不存在的父目录;若目录已存在,则返回false。
1.2 复制与移动
fs::copy("/tmp/source.txt", "/tmp/dest.txt", fs::copy_options::overwrite_existing);
fs::copy 默认不覆盖同名文件,可通过copy_options控制。移动同样可使用fs::rename或fs::move(C++23)。
1.3 删除文件/目录
fs::remove("/tmp/old.txt"); // 仅删除文件
fs::remove_all("/tmp/old_folder"); // 递归删除目录
2. 遍历目录
使用fs::directory_iterator或fs::recursive_directory_iterator可以轻松列出文件。
for (const auto& entry : fs::recursive_directory_iterator("/tmp"))
{
std::cout << entry.path() << '\n';
}
若只关心文件,可以过滤掉子目录:
for (const auto& entry : fs::recursive_directory_iterator("/tmp"))
{
if (entry.is_regular_file())
std::cout << entry.path() << '\n';
}
3. 读取文件元信息
fs::file_time_type ctime = fs::last_write_time("/tmp/example.txt");
auto s = fs::file_size("/tmp/example.txt");
last_write_time 返回的时间点可通过std::chrono转换为可读时间。
4. 路径操作
fs::path 对路径进行分割、拼接、相对化等操作。
fs::path p1("/usr");
fs::path p2("bin/g++");
fs::path full = p1 / p2; // /usr/bin/g++
fs::path relative = full.lexically_relative("/usr"); // bin/g++
lexically_normal() 可以去除多余的.和..,但不访问文件系统。
5. 高级技巧
5.1 与错误码配合使用
std::error_code 可以捕获异常信息,避免抛出。
std::error_code ec;
fs::remove("/tmp/nonexistent", ec);
if (ec) std::cerr << "删除失败: " << ec.message() << '\n';
5.2 对文件进行锁定(文件锁)
虽然std::filesystem本身不支持文件锁,但可配合系统API实现。示例(Linux):
#include <fcntl.h>
int fd = open("/tmp/file.txt", O_RDWR);
flock(fd, LOCK_EX); // 互斥锁
// 读写文件
flock(fd, LOCK_UN);
close(fd);
5.3 对大文件进行分块读取
使用std::ifstream与fs::file_size配合,可实现高效的分块读取。
std::ifstream ifs("/tmp/large.bin", std::ios::binary);
size_t size = fs::file_size(ifs);
size_t block = 1024 * 1024; // 1MB
std::vector <char> buffer(block);
while (ifs.read(buffer.data(), block))
{
// 处理 block 字节
}
6. 性能注意
- 对于大规模文件遍历,建议使用
fs::directory_options::skip_permission_denied避免因权限问题中断。 fs::file_size只对常规文件有效;对符号链接可使用symlink_status。
7. 结语
std::filesystem 的出现,大大降低了 C++ 文件系统编程的门槛。它统一了平台差异、提供了异常安全的接口,并与 STL 其他组件(如std::chrono、std::vector等)配合使用。掌握这一模块后,开发者可以更专注于业务逻辑,而非底层细节。祝你在项目中愉快地使用 std::filesystem,构建跨平台、可靠的文件操作功能。