C++space_info磁盘空间信息查询

2026-04-11 01:25:29 1062阅读 0评论

C++里查磁盘空间,别再手撕statvfs了:std::filesystem::space_info真香实测

上周帮同事调一个打包工具的崩溃问题,现象很诡异——程序在某台Windows机器上总提示“磁盘空间不足”,可资源管理器明明显示还有20GB空闲。最后发现,是代码里用GetDiskFreeSpaceEx时没区分lpFreeBytesAvailablelpTotalNumberOfFreeBytes,把“用户可用空间”错当成了“卷总空闲空间”。这事让我重新翻了遍C++17的<filesystem>,才发现space_info这个接口,不跨平台、不封装错误、不绕弯子,三行代码就能拿到真正该关心的三个数值

std::filesystem::space_info不是什么新概念,但它常被当成“玩具接口”忽略。很多人写完exists()is_directory()就收工,其实它藏了个极其实用的磁盘空间查询能力。关键在于:它返回的不是某个抽象的“剩余量”,而是三个有明确语义的字段——capacity(总容量)、free(卷上所有空闲字节)、available(当前进程实际能写入的字节数)。这三个数在Linux配了quota、Windows启用了配额或启用了压缩/重复数据删除的卷上,可能彼此差出好几个GB

怎么用?最简场景:检查某个路径所在分区是否够写一个500MB的临时文件。

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

bool has_enough_space(const fs::path& target, uintmax_t required_bytes) {
    try {
        auto space = fs::space(target); // 关键:传入任意路径,自动定位到其所在文件系统
        return space.available >= required_bytes;
    } catch (const fs::filesystem_error&) {
        return false; // 路径不可访问、无权限、跨网络挂载失败等
    }
}

// 调用示例
if (!has_enough_space("/tmp/cache", 500 * 1024 * 1024)) {
    std::cerr << "磁盘空间紧张,跳过缓存生成\n";
}

注意这里传的是target路径,不是设备名。fs::space()会自动解析路径归属的挂载点(Linux/macOS)或驱动器根目录(Windows),你不用自己realpath()再截字符串——这点比手动调statvfsGetDiskFreeSpaceEx省心太多。

但得说句实在话:space_info不是万能钥匙。它查的是“当前用户+当前进程上下文下的可用空间”,如果程序以管理员身份运行,而目标路径在受限用户目录下(比如C:\Users\Alice\AppData\Local),available反映的就是Alice的配额余量,不是系统总空闲。这反而是优点:它告诉你“你现在真能写多少”,而不是“理论上硬盘还剩多少”。

另一个容易踩的坑是单位。space_info里三个字段全是uintmax_t,单位是字节。别手痒去除1024再除1024——直接用std::format或手动换算更可控:

auto s = fs::space("/home");
std::cout << fmt::format("可用:{:.1f} GB", s.available / (1024.0 * 1024 * 1024));

如果你需要监控多个路径(比如日志目录、上传目录、缓存目录),别反复调fs::space()。实测在某些NAS挂载点上,每次调用都有毫秒级延迟。更稳的做法是缓存结果,加个30秒有效期

struct SpaceCache {
    mutable std::map<std::string, std::pair<fs::space_info, std::time_t>> cache;
    mutable std::shared_mutex mtx;

    fs::space_info get(const fs::path& p) const {
        auto key = p.root_path().string();
        std::shared_lock lock(mtx);
        auto it = cache.find(key);
        if (it != cache.end() && std::time(nullptr) - it->second.second < 30) {
            return it->second.first;
        }
        lock.unlock();

        std::unique_lock wlock(mtx);
        auto& entry = cache[key];
        entry.first = fs::space(p);
        entry.second = std::time(nullptr);
        return entry.first;
    }
};

最后提醒一个硬限制:fs::space()在C++17中是标准行为,但MSVC 19.26(VS 2019 16.6)之前、GCC 8.1之前、Clang 7.0之前均不完全支持。如果你还在维护老编译器环境,别硬切——宁可用条件编译兜底,也别让space_info变成程序启动时的第一个异常源。

回到开头那个打包工具的问题。改用fs::space()后,我们终于能准确判断:当available < required时,是真没空间了;而free > required && available < required,则说明是权限或配额卡住了——这时该提示用户“请检查磁盘配额设置”,而不是傻乎乎地报“磁盘已满”。

查磁盘空间这件事,从来就不是为了炫技。它关乎用户体验是否平滑,关乎后台任务会不会静默失败,更关乎运维排查时少花两小时。space_info不性感,不复杂,但它把一件琐碎又关键的事,干得干净利落。下次再看到磁盘告警,先别急着打开终端敲df -h——你的C++代码,本就可以自己回答这个问题。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,1062人围观)

还没有评论,来说两句吧...

目录[+]