如何正确获取文件大小并将其转换为Cocoa中的MB,GB?

Use*_*234 43 macos cocoa objective-c

可能重复:
用于将大小转换为人类可读字符串的ObjC/Cocoa类?

我是Cocoa的新手.我正在尝试正确获取文件夹文件的大小.如果小于1 GB或以GB为单位,则以MB为单位显示.

我希望它显示的方式是四舍五入,后面有一个数字.

5.5 如果MB大于1000> 1.1 GB,则为MB

我正在尝试使用它

 unsigned  long long size= ([[[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil] fileSize]);
Run Code Online (Sandbox Code Playgroud)

但我不能正确地转换数字,并按我的意愿显示它.

谢谢.

Par*_*fna 115

为了将文件大小转换为MB,Gb使用以下功能

- (id)transformedValue:(id)value
{

    double convertedValue = [value doubleValue];
    int multiplyFactor = 0;

    NSArray *tokens = @[@"bytes",@"KB",@"MB",@"GB",@"TB",@“PB”, @“EB”, @“ZB”, @“YB”];

    while (convertedValue > 1024) {
        convertedValue /= 1024;
        multiplyFactor++;
    }

    return [NSString stringWithFormat:@"%4.2f %@",convertedValue, tokens[multiplyFactor]];
}
Run Code Online (Sandbox Code Playgroud)

编辑:

您还可以使用NSByteCountFormatter类.适用于iOS 6.0/OS X v10.8及更高版本.

[NSByteCountFormatter stringFromByteCount:1999 countStyle:NSByteCountFormatterCountStyleFile];
Run Code Online (Sandbox Code Playgroud)

您可以使用NSByteCountFormatterCountStyleFile,NSByteCountFormatterCountStyleMemory,NSByteCountFormatterCountStyleDecimalNSByteCountFormatterCountStyleBinary在countStyle.

NSByteCountFormatterCountStyleFile:指定文件或存储字节计数的显示.此实际行为是特定于平台的; 在OS X 10.8上,这使用了十进制样式,但随着时间的推移可能会发生变化.

NSByteCountFormatterCountStyleMemory:指定内存字节计数的显示.此实际行为是特定于平台的; 在OS X 10.8上,它使用二进制样式,但这可能会随着时间而改变.

NSByteCountFormatterCountStyleDecimal:显式指定KB的字节数,1000字节显示为1 KB

NSByteCountFormatterCountStyleBinary:显式指定KB的字节数,1024字节显示为1 KB

  • 请使用适当的KiB/MiB /等作为二进制前缀.Apple已经切换到SI(十进制)前缀,并且一致性是一件好事. (2认同)

jrc*_*jrc 57

如果您的目标是OS X 10.8或iOS 6,则可以使用NSByteCountFormatter.

我会像这样写你的例子:

    NSError *error = nil;
    NSDictionary *attribs = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&error];
    if (attribs) {
        NSString *string = [NSByteCountFormatter stringFromByteCount:[attribs fileSize] countStyle:NSByteCountFormatterCountStyleFile];
        NSLog(@"%@", string);
    }
Run Code Online (Sandbox Code Playgroud)


Die*_*Epp 8

这是我图书馆的一段代码.(我特此在简化的BSD许可证下发布它.)它经过了相当广泛的测试,它完全正确地完成了所有舍入.这并不像听起来那么微不足道.它总是给出两个有效数字,除非它打印三个数字(例如,980 B),在这种情况下,所有三个数字都是重要的.

使用stringWithFormat:@"%..something...f"将不起作用,因为如果您将999999字节舍入到1000千字节,则需要将其显示为1.0 MB,而不是1000 kB.

请注意,此代码也会执行"银行家舍入"或"无偏舍入"或"舍入到均匀",无论您要将其称为什么.因此1050变为"1.0 kB",但1150变为"1.2 kB".这与printf我的系统完全相同,并且通常是这种事情的首选舍入方法.

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define SIZE_BUFSZ 7
static char const SIZE_PREFIXES[] = "kMGTPEZY";

void
format_size(char buf[SIZE_BUFSZ], uint64_t sz)
{
    int pfx = 0;
    unsigned int m, n, rem, hrem;
    uint64_t a;
    if (sz <= 0) {
        memcpy(buf, "0 B", 3);
        return;
    }
    a = sz;
    if (a < 1000) {
        n = a;
        snprintf(buf, SIZE_BUFSZ, "%u B", n);
        return;
    }
    for (pfx = 0, hrem = 0; ; pfx++) {
        rem = a % 1000ULL;
        a = a / 1000ULL;
        if (!SIZE_PREFIXES[pfx + 1] || a < 1000ULL)
            break;
        hrem |= rem;
    }
    n = a;
    if (n < 10) {
        if (rem >= 950) {
            buf[0] = '1';
            buf[1] = '0';
            buf[2] = ' ';
            buf[3] = SIZE_PREFIXES[pfx];
            buf[4] = 'B';
            buf[5] = '\0';
            return;
        } else {
            m = rem / 100;
            rem = rem % 100;
            if (rem > 50 || (rem == 50 && ((m & 1) || hrem)))
                m++;
            snprintf(buf, SIZE_BUFSZ,
                     "%u.%u %cB", n, m, SIZE_PREFIXES[pfx]);
        }
    } else {
        if (rem > 500 || (rem == 500 && ((n & 1) || hrem)))
            n++;
        if (n >= 1000 && SIZE_PREFIXES[pfx + 1]) {
            buf[0] = '1';
            buf[1] = '.';
            buf[2] = '0';
            buf[3] = ' ';
            buf[4] = SIZE_PREFIXES[pfx+1];
            buf[5] = 'B';
            buf[6] = '\0';
        } else {
            snprintf(buf, SIZE_BUFSZ,
                     "%u %cB", n, SIZE_PREFIXES[pfx]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是测试数据:

{ 0, "0 B" },
{ 5, "5 B" },
{ 20, "20 B" },
{ 100, "100 B" },
{ 500, "500 B" },
{ 999, "999 B" },
{ 1000, "1.0 kB" },
{ 1050, "1.0 kB" },
{ 1051, "1.1 kB" },
{ 2349, "2.3 kB" },
{ 2350, "2.4 kB" },
{ 9949, "9.9 kB" },
{ 9950, "10 kB" },
{ 10000, "10 kB" },
{ 10500, "10 kB" },
{ 10501, "11 kB" },
{ 99499, "99 kB" },
{ 99500, "100 kB" },
{ 999499, "999 kB" },
{ 999500, "1.0 MB" },
{ 1000000, "1.0 MB" },
{ 952500000, "952 MB" },
{ 952500001, "953 MB" },
{ 1000000000, "1.0 GB" },
{ 2300000000000ULL, "2.3 TB" },
{ 9700000000000000ULL, "9.7 PB" }
Run Code Online (Sandbox Code Playgroud)

  • @NiklasRingdahl:1 kB的国际标准是1000字节.关于这一点存在着长期的分歧,但最终,我将遵循自1799年以来一直存在的国际标准.苹果现在也遵循这一惯例,但几年前却没有.其他供应商也不一致.由于这是OS X问题,因此遵循Apple的主导并使用1000(除了遵循国际标准)也是一个好主意.1024的幂的标准前缀是Ki,Mi,Gi等,如果你想要二进制前缀,你应该使用这些前缀. (2认同)