广告

C++17 std::filesystem 怎么用?从入门到常用文件系统操作的完整指南

C++17 std::filesystem 入门与概念

为何在现代 C++ 项目中使用 std::filesystem

在 C++17 标准中,std::filesystem 提供了一组跨平台的文件系统操作接口,帮助开发者统一处理路径、遍历目录、创建或删除文件等能力。跨平台一致性是其最大的优势之一。

核心对象std::filesystem::path,它可以表示相对路径和绝对路径,并支持与字符串的互操作,提供了丰富的成员函数用于拼接、提取和规范化路径。

// 了解 path 的基本用法
#include 
#include 
namespace fs = std::filesystem;int main() {fs::path p = "logs/app.log";std::cout << "路径:" << p << std::endl;std::cout << "父级路径:" << p.parent_path() << std::endl;return 0;
}

快速起步:包含头文件、命名空间与基础操作

包含头文件与创建命名空间别名

首先添加头文件 <filesystem>,并在代码中使用 命名空间别名 以简化书写。

C++17 std::filesystem 怎么用?从入门到常用文件系统操作的完整指南

常见起步写法是 namespace fs = std::filesystem;,之后即可使用 fs::path 和其它 API。

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;int main() {fs::path p = "/var/log";std::cout << p << std::endl;return 0;
}

常用操作:路径与状态检查

路径存在性与类型判断

要判断路径是否存在,可以使用 fs::exists;要判断类型,可以组合使用 fs::is_regular_filefs::is_directory

错误处理也可以通过返回值与 std::error_code 或异常进行判断,提供了两种安全的错误处理路径。

#include <filesystem>
#include <iostream>
#include <system_error>
namespace fs = std::filesystem;int main() {fs::path p = "docs/report.txt";if (fs::exists(p)) {std::cout << p << " exists" << std::endl;if (fs::is_regular_file(p)) {std::cout << "是普通文件" << std::endl;}}return 0;
}

遍历目录:遍历、过滤与迭代器

使用目录遍历迭代器

遍历目录最直接的方法是 directory_iterator,它逐条枚举目录项并可通过 path() 访问子项路径,适合简单遍历。

对于递归遍历,可以使用 recursive_directory_iterator,它会遍历子目录及其子目录,常用于统计、搜索等场景。

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

文件创建与删除:复制、重命名、删除

创建目录与文件、以及删除操作

使用 fs::create_directoryfs::create_directories 来创建目录;创建文件通常通过写入操作实现,库本身提供了对路径的支持。

删除操作包括 fs::removefs::remove_all,前者仅删除单个文件或空目录,后者会递归删除目录及其内容。

#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;int main() {fs::path dir = "data/new_dir";if (fs::create_directories(dir)) {std::ofstream file((dir / "hello.txt").string());file << "hello";file.close();}// 删除操作示例fs::remove(dir / "hello.txt");fs::remove_all("data");return 0;
}

错误处理与异常安全

异常 vs 错误码(error_code)

std::filesystem 的大多数操作在异常模式下会抛出 std::filesystem::filesystem_error,也可以通过返回值与 std::error_code 或使用无抛出版本来处理错误。

在性能敏感的场景下,优先考虑带有 std::error_code 的版本,以避免异常带来的开销,同时也能清晰地获得错误信息。

#include <filesystem>
#include <system_error>
#include <iostream>
namespace fs = std::filesystem;int main() {std::error_code ec;if (!fs::exists("unknown.txt", ec)) {std::cerr << "错误:" << ec.message() << std::endl;}return 0;
}

跨平台注意事项与性能

跨平台差异与性能优化要点

虽然 std::filesystem 提供跨平台接口,但不同平台对路径分隔符、权限模型等仍有差异,开发时需要通过测试来确保行为一致性。

为了提升性能,尽量减少磁盘 I/O 的重复访问,例如将多次 exists 调用合并为一次结果缓存,并使用对等的 path 操作来避免不必要的 I/O。

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;int main() {fs::path root = "/opt/app";if (fs::exists(root)) {std::cout << "Root exists" << std::endl;}return 0;
}

广告

后端开发标签