当前位置: 首页 > news >正文

C++ 第三阶段 新标准库组件 - 第二节:std::filesystem(文件系统操作)

目录

一、std::filesystem 概述

1. 核心作用

2. 核心组件

二、std::filesystem 的基本用法

1. 路径操作(std::filesystem::path)

(1) 路径构造与拼接

(2) 路径分解

(3) 路径修改

2. 目录与文件操作

(1) 创建目录

(2) 删除目录

(3) 检查文件存在

(4) 查询文件属性

3. 目录遍历

(1) 非递归遍历

(2) 递归遍历

(3) 过滤条件

4. 文件与目录操作

(1) 复制文件或目录

(2) 移动文件或目录

三、错误处理机制

1. 异常处理

2. 基于错误码的处理

四、跨平台注意事项

1. 路径分隔符处理

示例:

2. 大小写敏感性

五、常见问题与解决方案

1. 路径拼接错误

问题:

解决方案:

2. 权限不足导致的操作失败

问题:

解决方案:

3. 递归遍历性能问题

问题:

解决方案:

六、示例代码汇总

示例 1:创建目录并检查文件大小

示例 2:递归删除目录

示例 3:遍历目录并统计文件数量

七、总结

1. std::filesystem 的核心优势

2. 适用场景

3. 最佳实践

C++从入门到入土学习导航_c++学习进程-CSDN博客


一、std::filesystem 概述

1. 核心作用

std::filesystem 是 C++17 引入的标准化文件系统操作库,基于 Boost.Filesystem 的功能实现。它解决了以下问题:

  • 跨平台兼容性:统一处理 Windows(使用 \ 分隔符)和 POSIX(使用 / 分隔符)系统的路径差异。
  • 类型安全:通过 std::filesystem::path 类封装路径操作,避免手动拼接字符串导致的错误。
  • 简化复杂操作:提供目录遍历、文件属性查询、路径分解等高阶功能。

2. 核心组件

类/函数功能描述
std::filesystem::path表示文件路径,支持路径拼接、分解、检查等操作。
std::filesystem::directory_iterator遍历目录中的条目。
std::filesystem::recursive_directory_iterator递归遍历目录及其子目录。
std::filesystem::create_directory创建单个目录。
std::filesystem::remove删除文件或空目录。
std::filesystem::exists检查文件或目录是否存在。
std::filesystem::file_size查询文件大小。
std::filesystem::copy复制文件或目录。

二、std::filesystem 的基本用法

1. 路径操作(std::filesystem::path

(1) 路径构造与拼接
#include <filesystem>
#include <iostream>namespace fs = std::filesystem;int main() {fs::path p1 = "C:/Users/Example"; // Windows 路径fs::path p2 = "/home/user/documents"; // Linux 路径fs::path p3 = p1 / "data" / "file.txt"; // 自动适配系统分隔符std::cout << "Path: " << p3 << std::endl;std::cout << "Native path: " << p3.native() << std::endl; // 显示系统原生格式
}
(2) 路径分解
fs::path p = "C:/Users/Example/data/file.txt";
std::cout << "Root name: " << p.root_name() << std::endl;       // C:
std::cout << "Root path: " << p.root_path() << std::endl;       // C:/
std::cout << "Relative path: " << p.relative_path() << std::endl; // Users/Example/data/file.txt
std::cout << "Parent path: " << p.parent_path() << std::endl;   // C:/Users/Example/data
std::cout << "Filename: " << p.filename() << std::endl;         // file.txt
std::cout << "Stem: " << p.stem() << std::endl;                 // file
std::cout << "Extension: " << p.extension() << std::endl;       // .txt
(3) 路径修改
fs::path p = "C:/Users/Example/data/file.txt";
p.remove_filename(); // 移除文件名部分 → C:/Users/Example/data/
p.replace_extension(".bak"); // 修改后缀 → C:/Users/Example/data/file.bak
p.make_preferred(); // 转换为系统首选分隔符 → C:\Users\Example\data\file.bak (Windows)

2. 目录与文件操作

(1) 创建目录
fs::create_directory("new_dir"); // 创建单级目录(父目录必须存在)
fs::create_directories("nested_dir/sub_dir"); // 递归创建多级目录
(2) 删除目录
fs::remove("empty_dir"); // 删除空目录
fs::remove_all("dir_with_files"); // 递归删除目录及内容
(3) 检查文件存在
if (fs::exists("example.txt")) {std::cout << "File exists!" << std::endl;
} else {std::cout << "File not found." << std::endl;
}
(4) 查询文件属性
if (fs::exists("example.txt")) {std::cout << "File size: " << fs::file_size("example.txt") << " bytes" << std::endl;std::cout << "Last modified time: " << fs::last_write_time("example.txt") << std::endl;
}

3. 目录遍历

(1) 非递归遍历
for (const auto& entry : fs::directory_iterator("C:/")) {std::cout << "Entry: " << entry.path() << std::endl;
}
(2) 递归遍历
for (const auto& entry : fs::recursive_directory_iterator(".")) {std::cout << "Recursive entry: " << entry.path() << std::endl;
}
(3) 过滤条件
for (const auto& entry : fs::directory_iterator(".")) {if (entry.is_regular_file() && entry.path().extension() == ".cpp") {std::cout << "C++ source file: " << entry.path() << std::endl;}
}

4. 文件与目录操作

(1) 复制文件或目录
fs::copy("source.txt", "destination.txt"); // 复制文件
fs::copy("source_dir", "destination_dir", fs::copy_options::recursive); // 递归复制目录
(2) 移动文件或目录
fs::rename("old_name.txt", "new_name.txt"); // 重命名文件
fs::rename("old_dir", "new_dir"); // 重命名目录

三、错误处理机制

1. 异常处理

默认情况下,std::filesystem 会抛出 std::filesystem::filesystem_error 异常:

try {fs::remove("nonexistent_file");
} catch (const fs::filesystem_error& e) {std::cerr << "Error: " << e.what() << std::endl;
}

2. 基于错误码的处理

通过传递 std::error_code 参数,避免异常抛出:

std::error_code ec;
fs::remove("nonexistent_file", ec);
if (ec) {std::cerr << "Error: " << ec.message() << std::endl;
}

四、跨平台注意事项

1. 路径分隔符处理

  • Windows:使用 \ 作为路径分隔符,但 std::filesystem::path 会自动将 / 转换为 \
  • POSIX:使用 / 作为路径分隔符,std::filesystem::path 会保持原样。
示例:
fs::path p1 = "C:/Users/Example"; // Windows 下自动转换为 C:\Users\Example
fs::path p2 = "/home/user/documents"; // Linux 下保持不变

2. 大小写敏感性

  • Windows:路径大小写不敏感。
  • Linux/macOS:路径大小写敏感。

五、常见问题与解决方案

1. 路径拼接错误

问题:

手动拼接路径可能导致分隔符错误(如 C:/Users/Example\file.txt)。

解决方案:

使用 std::filesystem::path/ 操作符自动适配分隔符。


2. 权限不足导致的操作失败

问题:

尝试删除或修改受保护的文件或目录时抛出异常。

解决方案:
  • 使用 try-catch 捕获异常或检查错误码。
  • 在操作系统中提升权限后再执行操作。

3. 递归遍历性能问题

问题:

recursive_directory_iterator 可能因大量文件导致性能下降。

解决方案:
  • 添加过滤条件减少遍历范围。
  • 在非实时场景中异步处理。

六、示例代码汇总

示例 1:创建目录并检查文件大小

#include <filesystem>
#include <iostream>namespace fs = std::filesystem;int main() {fs::path dir = "example_dir";if (!fs::exists(dir)) {fs::create_directory(dir);std::cout << "Directory created: " << dir << std::endl;}fs::path file = dir / "example.txt";std::ofstream(file) << "Hello, filesystem!"; // 写入内容if (fs::exists(file)) {std::cout << "File size: " << fs::file_size(file) << " bytes" << std::endl;}return 0;
}

示例 2:递归删除目录

#include <filesystem>
#include <iostream>namespace fs = std::filesystem;int main() {fs::path dir = "test_dir";if (fs::exists(dir)) {fs::remove_all(dir);std::cout << "Directory removed: " << dir << std::endl;} else {std::cout << "Directory does not exist." << std::endl;}return 0;
}

示例 3:遍历目录并统计文件数量

#include <filesystem>
#include <iostream>namespace fs = std::filesystem;int main() {int file_count = 0;for (const auto& entry : fs::recursive_directory_iterator(".")) {if (entry.is_regular_file()) {++file_count;}}std::cout << "Total files: " << file_count << std::endl;return 0;
}

七、总结

1. std::filesystem 的核心优势

  • 跨平台兼容性:统一处理不同操作系统的路径差异。
  • 类型安全:通过 path 类避免手动拼接路径错误。
  • 简化复杂操作:提供高阶 API(如目录遍历、属性查询)。

2. 适用场景

  • 文件管理工具:如资源管理器、备份工具。
  • 自动化脚本:批量处理文件或目录。
  • 跨平台应用:需要兼容 Windows 和 Linux 的项目。

3. 最佳实践

  • 优先使用 std::filesystem::path:替代字符串拼接。
  • 结合异常处理与错误码:根据需求选择错误处理方式。
  • 注意递归操作的性能:添加过滤条件或异步处理。

通过掌握 std::filesystem,开发者可以高效、安全地处理文件系统操作,构建跨平台且健壮的 C++ 应用程序。

相关文章:

  • 设计模式-代理模式、装饰者模式
  • Vue3—插槽solt
  • 微机系统 - 第7章 -可编程接口芯片
  • 概率概率密度
  • GO 语言学习 之 函数
  • 基于MFC的遥感图像匹配程序设计
  • 前端进阶之路-从传统前端到VUE-JS(第一期-VUE-JS环境配置)(Node-JS环境配置)(Node-JS/npm换源)
  • SQL 子查询全位置解析:可编写子查询的 7 大子句
  • Hyper-v-中的FnOs--飞牛Nas虚拟磁盘扩容(不清除数据)
  • Java安装与使用教程
  • 栅极驱动器选的好SiC MOSFET高效又安全
  • Gradio全解13——MCP详解(4)——TypeScript包命令:npm与npx
  • 【龙泽科技】新能源汽车故障诊断仿真教学软件【吉利几何G6】
  • SRS WebRTC 入门
  • 【数据标注师】分类标注
  • Push-T, AloHa, Rlbench三个仿真环境信息
  • 为何需要防爆平板?它究竟有何能耐?
  • 给定一个整型矩阵map,求最大的矩形区域为1的数量
  • Redis 高可用分片集群:主从模式与哨兵机制详解
  • 【AI智能体】Dify 核心组件从使用到实战操作详解