std::filesystem::file_size() 是 C++17 起跨平台获取文件大小的最直接方式,返回 std::uintmax_t 字节数,仅适用于常规文件,否则抛 filesystem_error,需注意编译器支持与显式链接。

用 std::filesystem 获取文件大小和属性,是 C++17 起最直接、跨平台的方式;不需要系统 API 或第三方库,但要注意编译器支持和异常处理。
检查编译器是否支持 std::filesystem
不是所有 C++17 编译器默认启用该库。GCC 8+、Clang 7+、MSVC 2017 15.7+ 支持,但需显式链接:
- GCC/Clang:编译时加
-lstdc++fs(GCC)或-lc++fs(Clang) - MSVC:无需额外链接,但需确保
/std:c++17或更高 - 若链接失败且报
undefined reference to 'std::filesystem::file_size',大概率是漏了链接选项
std::filesystem::file_size() 获取文件大小
它返回 std::uintmax_t(通常为 uint64_t),单位是字节;只对常规文件有效,对目录、符号链接(未解引用)、不存在路径会抛 std::filesystem::filesystem_error。
try {
auto size = std::filesystem::file_size("/path/to/file.txt");
std::cout << "Size: " << size << " bytes\n";
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Cannot get size: " << e.what() << "\n";
}
- 若想安全获取符号链接指向的目标大小,用
std::filesystem::file_size(path, ec)形式,配合std::error_code& ec避免异常 - 对目录调用会抛异常——别误以为能拿到目录“大小”,它不等价于总占用空间
- 注意:NTFS 稀疏文件或某些网络文件系统可能返回逻辑大小而非实际磁盘占用
用 std::filesystem::status() 和 std::filesystem::symlink_status() 判断类型与权限
这两个函数返回 std::filesystem::file_status,可进一步用 type() 和 permissions() 提取信息:
立即学习“C++免费学习笔记(深入)”;
namespace fs = std::filesystem;
fs::path p = "/etc/passwd";
auto stat = fs::status(p); // 跟随符号链接
// auto stat = fs::symlink_status(p); // 不跟随,保留链接本身
if (stat.type() == fs::file_type::regular) {
std::cout << "Regular file\n";
}
if ((stat.permissions() & fs::perms::owner_read) != fs::perms::none) {
std::cout << "Owner can read\n";
}
-
status()解引用符号链接,symlink_status()不解引用——这对判断“是不是链接”很关键 - 权限值是位掩码,必须用
&检查,不能直接比较(如stat.permissions() == fs::perms::owner_read是错的) - Windows 下部分权限位(如 group/other)始终为
fs::perms::none,不要依赖它们做跨平台逻辑
一次性读取完整属性:std::filesystem::directory_entry
当遍历目录或需要多项元数据时,用 directory_entry 更高效——它在首次访问时缓存 status() 结果,避免重复系统调用:
for (const auto& entry : fs::directory_iterator("/tmp")) {
try {
auto sz = entry.file_size(); // 不再触发新 stat()
auto tp = entry.last_write_time();
std::cout << entry.path().filename() << ": "
<< sz << "B, modified at " << tp << "\n";
} catch (const fs::filesystem_error&) {
continue; // 忽略无权限或已删除项
}
}
- 构造
directory_entry本身不访问文件系统;只有调用file_size()、last_write_time()等才真正读取 - 如果后续还要调用
entry.is_regular_file()或entry.status(),它们复用同一份缓存,比单独调用fs::file_size(p)+fs::status(p)更快 - 注意:缓存仅对单个
entry实例有效;不同entry对象之间不共享
真正容易被忽略的是错误处理粒度:很多人只在顶层 try/catch,但像遍历目录这种操作,个别文件不可读很常见,应该对每个 entry 单独捕获,而不是让整个循环因一个坏路径中断。











