C++17如何操作文件和目录?(filesystem库用法)

C++17 库以 std::filesystem::path 为核心,提供跨平台路径操作、状态查询、目录遍历及文件系统修改功能,需链接对应标准库组件并启用 C++17。

用 C++17 的 库操作文件和目录,核心是 std::filesystem::path 和各类自由函数(如 existscreate_directorycopy 等),所有功能都基于路径抽象,无需手动拼接字符串或调用系统 API。

构造和处理路径

std::filesystem::path 是路径的智能封装,自动处理分隔符(Windows 用 \,Linux/macOS 用 /),支持多种构造方式,还能拆解、拼接、规范化:

  • 直接用字符串字面量构造:fs::path p = "data/logs/app.log";
  • / 操作符拼接(推荐):fs::path p = "data" / "logs" / "app.log";
  • 获取父目录:p.parent_path();获取文件名:p.filename();获取扩展名:p.extension()
  • 标准化路径(处理 ...):p = p.lexically_normal();

判断与查询文件/目录状态

status()symlink_status() 获取文件状态,再配合类型判断函数,避免竞态条件(即“检查后使用”不安全):

  • 存在且是普通文件:fs::is_regular_file(p)
  • 存在且是目录:fs::is_directory(p)
  • 是否为符号链接:fs::is_symlink(p)
  • 获取大小(仅对常规文件有效):fs::file_size(p)
  • 获取最后修改时间:fs::last_write_time(p)

注意:不要先调 exists() 再调 is_regular_file(),应直接用后者——它内部已包含存在性检查。

创建、删除与移动文件/目录

所有操作都返回 bool 表示是否成功(失败通常因权限不足或路径无效),不抛异常(除非明确启用异常模式):

  • 创建单层目录:fs::create_directory("my_folder")
  • 递归创建多级目录:fs::create_directories("a/b/c")
  • 删除空目录:fs::remove("empty_dir")
  • 递归删除整个目录树:fs::remove_all("project_build")
  • 重命名或移动(跨卷可能变为复制+删除):fs::rename("old.txt", "new.txt")
  • 复制文件(不支持目录):fs::copy_file("src.txt", "dst.txt", fs::copy_options::overwr

    ite_existing)

遍历目录内容

fs::directory_iterator 遍历单层,用 fs::recursive_directory_iterator 深度遍历。迭代器解引用得到 fs::directory_entry,可直接调用状态相关方法:

  • 遍历当前目录所有条目:for (const auto& entry : fs::directory_iterator("src")) { ... }
  • 跳过符号链接指向的目标,只遍历链接本身:fs::directory_iterator(p, fs::directory_options::skip_permission_denied)
  • 过滤出所有 .cpp 文件:if (entry.path().extension() == ".cpp") { ... }
  • 获取每个条目的文件大小:entry.file_size()(比反复调 fs::file_size(entry.path()) 更高效)

遍历时建议捕获 fs::filesystem_error 异常(例如权限拒绝),尤其在不可信路径上。

编译与注意事项

需显式链接标准库的 filesystem 组件:

  • Clang/GCC:加 -lstdc++fs(GCC 9+ 可能不需要)或 -lc++fs(Clang + libc++)
  • MSVC:默认支持,无需额外链接
  • 确保编译器启用 C++17:-std=c++17
  • 头文件必须写全:#include ,并建议用 namespace fs = std::filesystem; 简化书写

该库不提供文本读写能力——读写文件内容仍需 或第三方库;它专注路径管理与元数据操作。