std::filesystem::create_directories 是 C++17 标准推荐解法,可一次性递归创建完整路径;误用无 s 的 create_directory 会因上级缺失而失败;需检查返回值并验证目录可写性,而非仅依赖异常。

std::filesystem::create_directories 是 C++17 的标准解法
不用自己递归写逻辑,std::filesystem::create_directories 就是专为这事设计的:一次性创建完整路径,中间缺失的父目录自动补全。它比老式 mkdir 系统调用或 Boost.Filesystem 更轻量、更可移植,前提是编译器支持 C++17 且开了 stdc++fs 链接(GCC 需显式加 -lstdc++fs)。
常见错误现象:std::filesystem::create_directory(注意没 s)只建最后一级,路径中任意上级不存在就直接失败,抛出 std::filesystem::filesystem_error;有人误用它替代 create_directories,结果在 Windows 或 macOS 上跑一半就崩。
- 使用场景:初始化日志目录、缓存路径、配置文件存放位置等不确定上级是否存在的路径
- 参数差异:
create_directories接受std::filesystem::path或字符串字面量,不接受 C 风格const char*(会隐式转换但不推荐) - 性能影响:内部做路径分段 + 逐级检查,但对普通应用几乎无感;若路径极深(>100 级),可能有微小开销,但远小于手写循环出错重试的成本
- 兼容性:MSVC 2019 16.10+、Clang 10+、GCC 8+ 均支持;GCC 8–9 需链接
-lstdc++fs,GCC 10+ 默认内置
示例:
#include <filesystem>
namespace fs = std::filesystem;
int main() {
try {
fs::create_directories("logs/2024/06/15"); // 自动建 logs → 2024 → 06 → 15
} catch (const fs::filesystem_error& e) {
// e.what() 包含具体失败点,比如 "No such file or directory"
}
}
Windows 下 CreateDirectoryA/W 容易漏掉 ERROR\_PATH\_NOT\_FOUND
Win32 API 的 CreateDirectoryA 和 CreateDirectoryW 不递归,必须手动拆路径、从根开始逐级调用。最常踩的坑是没检查返回值为 false 时的 GetLastError() —— 很多时候不是权限问题,而是上级目录根本不存在,错误码是 ERROR_PATH_NOT_FOUND,不是 ERROR_ACCESS_DENIED。
立即学习“C++免费学习笔记(深入)”;
- 使用场景:需要精细控制每级创建行为(比如跳过已存在目录、记录哪一级新建成功)、或项目不能用 C++17
- 参数差异:
CreateDirectoryW接LPCWSTR(宽字符),CreateDirectoryA接LPCSTR(ANSI),中文路径务必用W版本,否则乱码导致创建失败 - 兼容性影响:Linux/macOS 完全不可用,跨平台项目需条件编译,维护成本高
- 容易忽略:调用前必须确保路径末尾无斜杠(如
"data//"可能被某些版本拒绝),且不能是相对路径中的".."连续段(系统会拒绝解析)
std::filesystem::create_directories 返回值别忽略
它返回 bool:成功创建至少一个新目录时为 true,所有目录都已存在时为 false。很多人只关心是否报异常,却忽略这个返回值 —— 导致误判“路径已就绪”,实际只是碰巧全存在,后续写文件时因权限不足或只读挂载而失败。
- 典型误用:把
create_directories当作“确保路径可用”的万能开关,不检查返回值也不验证最终目录是否可写 - 正确做法:先调用,再用
fs::is_directory+fs::status查权限位(Linux/macOS)或GetFileAttributes(Windows)确认可写 - 性能提示:重复调用
create_directories开销很小(只查不建),但频繁验证权限可能触发系统调用,生产环境建议缓存判断结果
第三方库(如 Boost)现在基本没必要引入
Boost.Filesystem 在 C++17 前是主流方案,但现在 std::filesystem 已覆盖其 95% 以上能力,且无额外依赖。唯一还值得考虑 Boost 的情况是:项目卡在 C++11/C++14,又不愿升级工具链,且已有大量 Boost 文件操作代码。
- 风险点:Boost 1.70+ 对
create_directories的行为和标准库不完全一致(比如符号链接处理策略),混用容易出边界问题 - 编译负担:Boost.Filesystem 需要编译并链接
boost_filesystem,静态链接时体积增加明显;而std::filesystem是标准库一部分,链接更轻 - 调试友好度:标准库异常类型统一为
std::filesystem::filesystem_error,堆栈更干净;Boost 报错信息有时夹杂实现细节,定位慢半拍
路径创建看着简单,但跨平台时 Windows 的长路径限制、Linux 的 umask 继承、macOS 的 case-insensitive 文件系统,都会让“建好就能用”变成陷阱。最稳妥的做法永远是:建完立刻尝试创建一个临时文件再删掉,而不是只信返回值或异常有没有抛。



















