You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS下调用statfs无法获取完整磁盘容量,原因是什么?

macOS下statfs获取磁盘容量与Finder显示不一致的问题

问题描述

你在macOS应用中尝试获取存储驱动器的容量及可用空间,执行了以下代码:

struct statfs stStg;

if(statfs(".", &stStg) == 0)
{
    uint64_t total_sz = stStg.f_bsize * stStg.f_blocks;
    uint64_t free_sz = stStg.f_bsize * stStg.f_bfree;

    double fTotal = (double)total_sz / (1024.0 * 1024.0 * 1024.0);
    double fFree = (double)free_sz / (1024.0 * 1024.0 * 1024.0);

    printf("%.02f GB (%.01f%% free)",
                 fTotal,
                 100.0 * fFree / fTotal);
}

代码返回结果:

460.43 GB (66.5% free)

但Finder中显示的磁盘容量更大,需要找出问题所在。

问题原因

  • 单位换算差异:Finder采用十进制换算(1GB = 1000³字节),而你的代码用的是二进制换算(1GiB = 1024³字节),这是数值差异的直接原因。
  • statfs字段的含义局限:
    1. f_blocks统计的是文件系统分配给用户使用的总块数,不包含macOS系统预留的空间(比如APFS的快照、系统备份分区等),而Finder显示的是磁盘的物理总容量。
    2. f_bfree是超级用户才能使用的空闲块数,普通用户实际可用的空闲空间应该用f_bavail字段。

修正方案

1. 匹配Finder的单位换算

如果要让数值和Finder显示对齐,把换算基数改成1000,同时替换正确的空闲空间字段:

struct statfs stStg;

if(statfs(".", &stStg) == 0)
{
    uint64_t total_sz = stStg.f_bsize * stStg.f_blocks;
    // 改用f_bavail获取普通用户可用空间
    uint64_t free_sz = stStg.f_bsize * stStg.f_bavail;

    // 十进制GB换算
    double fTotal = (double)total_sz / (1000.0 * 1000.0 * 1000.0);
    double fFree = (double)free_sz / (1000.0 * 1000.0 * 1000.0);

    printf("%.02f GB (%.01f%% free)",
                 fTotal,
                 100.0 * fFree / fTotal);
}

2. 获取磁盘物理总容量的方法

如果需要获取和Finder完全一致的物理总容量,statfs无法直接做到,建议使用Apple提供的更高阶API:

Objective-C示例(NSFileManager)

NSURL *rootURL = [NSURL fileURLWithPath:@"/"];
NSArray *keys = @[NSURLVolumeTotalCapacityKey, NSURLVolumeAvailableCapacityForImportantUsageKey];
NSError *error = nil;
NSDictionary *volumeAttrs = [rootURL resourceValuesForKeys:keys error:&error];

if (!error) {
    uint64_t totalCapacity = [volumeAttrs[NSURLVolumeTotalCapacityKey] unsignedLongLongValue];
    uint64_t availableCapacity = [volumeAttrs[NSURLVolumeAvailableCapacityForImportantUsageKey] unsignedLongLongValue];
    
    double totalGB = (double)totalCapacity / (1000.0 * 1000.0 * 1000.0);
    double availableGB = (double)availableCapacity / (1000.0 * 1000.0 * 1000.0);
    
    NSLog(@"%.02f GB (%.01f%% free)", totalGB, 100.0 * availableGB / totalGB);
}

Swift示例

let rootURL = URL(fileURLWithPath: "/")
do {
    let attrs = try rootURL.resourceValues(forKeys: [.volumeTotalCapacityKey, .volumeAvailableCapacityForImportantUsageKey])
    if let total = attrs.volumeTotalCapacity, let available = attrs.volumeAvailableCapacityForImportantUsage {
        let totalGB = Double(total) / (1000 * 1000 * 1000)
        let availableGB = Double(available) / (1000 * 1000 * 1000)
        print(String(format: "%.02f GB (%.01f%% free)", totalGB, 100.0 * availableGB / totalGB))
    }
} catch {
    print("获取磁盘信息失败:\(error)")
}

内容的提问来源于stack exchange,提问作者c00000fd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:03:10