C++17 文件系统
外观
C++17文件系统[编辑 | 编辑源代码]
介绍[编辑 | 编辑源代码]
C++17引入了<filesystem>库(正式名称为std::filesystem),提供了一套跨平台的文件和目录操作接口。该库基于Boost.Filesystem,允许开发者以统一的方式处理文件路径、遍历目录、检查文件属性以及执行文件操作(如复制、移动和删除)。
文件系统库的核心目标是:
- 提供平台无关的路径表示
- 支持递归目录遍历
- 实现文件元数据查询(如大小、权限、类型)
- 封装常见文件操作(如创建/删除目录)
核心组件[编辑 | 编辑源代码]
文件系统库主要包含以下类和函数:
组件 | 描述 |
---|---|
std::filesystem::path |
表示文件系统路径的类 |
std::filesystem::directory_entry |
目录项信息(缓存文件属性) |
std::filesystem::directory_iterator |
非递归目录遍历器 |
std::filesystem::recursive_directory_iterator |
递归目录遍历器 |
std::filesystem::file_status |
文件类型和权限信息 |
基本用法[编辑 | 编辑源代码]
路径操作[编辑 | 编辑源代码]
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem; // 命名空间别名
int main() {
// 构造路径对象
fs::path p1 = "/usr/local/include";
fs::path p2 = "config.h";
// 路径拼接和规范化
fs::path full_path = p1 / p2;
std::cout << "完整路径: " << full_path << '\n'
<< "父目录: " << full_path.parent_path() << '\n'
<< "文件名: " << full_path.filename() << '\n'
<< "扩展名: " << full_path.extension() << '\n';
// 路径存在性检查
if (fs::exists(full_path)) {
std::cout << "文件存在\n";
}
}
输出示例(Linux系统):
完整路径: "/usr/local/include/config.h" 父目录: "/usr/local/include" 文件名: "config.h" 扩展名: ".h" 文件存在
文件操作[编辑 | 编辑源代码]
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
void demo_file_ops() {
fs::path demo_dir = "test_dir";
// 创建目录
if (!fs::exists(demo_dir)) {
fs::create_directory(demo_dir);
std::cout << "目录创建成功\n";
}
// 创建空文件
fs::path file1 = demo_dir / "data.txt";
std::ofstream(file1).put('a'); // 创建文件并写入一个字符
// 文件信息
std::cout << "文件大小: " << fs::file_size(file1) << " bytes\n"
<< "最后修改时间: " << fs::last_write_time(file1).time_since_epoch().count() << '\n';
// 复制文件
fs::path file2 = demo_dir / "data_backup.txt";
fs::copy_file(file1, file2);
// 删除操作
fs::remove(file1);
fs::remove_all(demo_dir); // 递归删除目录
}
高级特性[编辑 | 编辑源代码]
目录遍历[编辑 | 编辑源代码]
递归遍历目录结构(使用mermaid展示流程):
代码实现:
void list_files(const fs::path& dir_path) {
try {
for (const auto& entry : fs::recursive_directory_iterator(dir_path)) {
auto status = entry.status();
std::cout << (fs::is_directory(status) ? "[D] " :
fs::is_symlink(status) ? "[L] " : "[F] ")
<< entry.path() << '\n';
}
} catch (const fs::filesystem_error& e) {
std::cerr << "错误: " << e.what() << '\n';
}
}
文件系统空间[编辑 | 编辑源代码]
查询磁盘空间信息:
void show_disk_usage(const fs::path& path) {
fs::space_info si = fs::space(path);
std::cout << "在 " << path << ":\n"
<< "总空间: " << si.capacity/1'000'000 << " MB\n"
<< "可用空间: " << si.available/1'000'000 << " MB\n"
<< "空闲空间: " << si.free/1'000'000 << " MB\n";
}
错误处理[编辑 | 编辑源代码]
文件系统操作可能抛出std::filesystem::filesystem_error
异常,最佳实践是:
- 检查文件存在性(
exists()
) - 捕获特定异常
- 使用
error_code
参数的无异常版本
示例:
void safe_remove(const fs::path& p) {
std::error_code ec;
if (!fs::remove(p, ec)) {
std::cerr << "删除失败: " << ec.message() << '\n';
}
}
实际应用案例[编辑 | 编辑源代码]
场景: 实现一个简单的项目清理工具,删除构建目录中的所有临时文件(*.tmp, *.bak)
void clean_project(const fs::path& project_dir) {
const std::vector<std::string> ext_to_remove = {".tmp", ".bak"};
for (const auto& entry : fs::recursive_directory_iterator(project_dir)) {
if (!entry.is_regular_file()) continue;
const std::string ext = entry.path().extension().string();
if (std::find(ext_to_remove.begin(), ext_to_remove.end(), ext) != ext_to_remove.end()) {
std::cout << "删除: " << entry.path() << '\n';
fs::remove(entry.path());
}
}
}
跨平台注意事项[编辑 | 编辑源代码]
- Windows路径使用反斜杠(
\
),但path
类会自动处理 - 符号链接行为在不同系统上可能不同
- 文件权限模型在Unix和Windows上有显著差异
性能考虑[编辑 | 编辑源代码]
directory_entry
会缓存文件属性,减少重复系统调用- 递归遍历可能消耗较多内存,对于超大目录结构
- 频繁调用
last_write_time
等函数可能影响性能
数学表示[编辑 | 编辑源代码]
文件系统空间计算可用百分比公式:
总结[编辑 | 编辑源代码]
C++17文件系统库提供了:
- 统一的跨平台路径处理
- 完整的文件和目录操作集合
- 类型安全的接口设计
- 异常和错误码双重错误处理机制
对于需要文件操作的现代C++项目,应优先使用std::filesystem
而非平台特定API。