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+ 支持,但需显式链接:
-lstdc++fs(GCC)或 -lc++fs(Clang)/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 避免异常std::filesystem::status() 和 std::filesystem::symlink_status() 判断类型与权限这两个函数返回 std::filesystem::file_status,可进一步用 type() 和 permissions() 提取信息:
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 是错的)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 单独捕获,而不是让整个循环因一个坏路径中断。