C++如何获取文件夹大小:递归遍历与file_size函数实战

使用 std::filesystem::file_size 前必须检查文件类型
直接对目录路径调用 std::filesystem::file_size 会抛出 std::filesystem::filesystem_error 异常,提示“No such file or directory”或“Invalid argument”。这并非路径错误,而是因为该函数仅适用于普通文件。因此,在获取文件大小前,务必使用 is_regular_file() 进行判断,并通过 is_directory() 对目录进行分流处理。
常见错误写法:
auto size = file_size(path); // 若path是文件夹,程序将崩溃
正确的做法是:在遍历文件系统前,先检查条目类型,主动跳过符号链接(除非需要追踪)、套接字、设备文件等非数据实体,确保计算准确。
递归遍历目录需手动控制或使用 recursive_directory_iterator
C++17 提供的 std::filesystem::recursive_directory_iterator 是实现递归遍历的最简方案。但需注意,其默认会跟随符号链接进入目标目录,可能导致重复计算甚至陷入无限循环。在生产环境中,建议禁用符号链接跟随:
立即学习“C++免费学习笔记(深入)”;
- 构造迭代器时传入
std::filesystem::directory_options::skip_permission_denied选项,避免因权限不足导致遍历中断 - 显式检查
iter->is_symlink()并跳过,而非依赖follow_symlinks = false(不同标准库实现行为可能不一致) - 注意:在 Windows 平台下,NTFS 符号链接与 junction point 表现不同。
is_symlink()对 junction 不返回 true,需额外判断is_directory()并结合status().type() == file_type::junction
累加文件大小时需防范 uintmax_t 溢出与静默I/O错误
std::filesystem::file_size 返回类型为 uintmax_t。虽然单个超大文件(如超过16TB)在某些平台可能引发溢出,但更常见的问题是因权限不足或路径失效导致的异常。不能假定每次 file_size() 调用都会成功:
- 将
file_size()调用置于try/catch块中,捕获std::filesystem::filesystem_error异常 - 对读取失败的文件记录警告信息(例如输出至
std::cerr),但不应中断整个遍历过程 - 避免使用
std::accumulate等无内置异常处理的泛型算法,手动编写循环能提供更精细的控制
核心代码示例:
uintmax_t total = 0;
for (auto iter = fs::recursive_directory_iterator(root, opts); iter != fs::recursive_directory_iterator(); ++iter) {
if (iter->is_symlink()) continue;
if (fs::is_regular_file(iter->status())) {
try {
total += fs::file_size(iter->path());
} catch (const fs::filesystem_error&) {
std::cerr << "Skip unreadable file: " << iter->path().string() << "";
}
}
}
Windows平台下长路径与特殊目录的额外处理
Windows 系统默认路径长度限制为 260 个字符,虽然使用 \?\ 前缀可以绕过,但 std::filesystem 在 MSVC 19.28 及以上版本才默认支持长路径。若遇到 filesystem_error 并提示“The system cannot find the path specified”,请优先检查:
- 程序清单(manifest)是否已声明
longPathAware=true - 注册表项
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlFileSystemLongPathsEnabled的值是否已设为 1 - 主动跳过系统保护目录(如
C:Recycler、C:System Volume Information),这些目录即使拥有管理员权限也常被拒绝访问
在实际开发中,建议首次遍历时启用 --dry-run 模式,仅统计可访问的子项数量,评估可行性后再决定是否进行完整的文件夹大小计算。
