c++如何获取文件大小和属性_c++ std::filesystem库路径操作【实战】

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() 提取信息:

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 单独捕获,而不是让整个循环因一个坏路径中断。