可能重复:
ObjC/Cocoa class for converting size to human-readable string?
我是Cocoa的新手。我正在尝试正确获取文件夹文件的大小。如果小于1 GB或以GB为单位,则以MB为单位显示。
我希望它显示的方式是在点之后用一个数字四舍五入。
实施例 5.5 MB 如果超过1000> 1.1 GB
我正在尝试使用此
unsigned long long size= ([[[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil] fileSize]);
但我不能正确地转换数字,并按照我想要的方式显示它。
感谢。
答案 0 :(得分: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]];
}
编辑:
您也可以使用NSByteCountFormatter课程。适用于iOS 6.0 / OS X v10.8及更高版本。
[NSByteCountFormatter stringFromByteCount:1999 countStyle:NSByteCountFormatterCountStyleFile];
您可以在countStyle中使用NSByteCountFormatterCountStyleFile
,NSByteCountFormatterCountStyleMemory
,NSByteCountFormatterCountStyleDecimal
或NSByteCountFormatterCountStyleBinary
。
NSByteCountFormatterCountStyleFile :指定文件或存储字节计数的显示。这个的实际行为是 特定于平台的;在OS X 10.8上,这使用了十进制样式,但是 可能随着时间而改变。
NSByteCountFormatterCountStyleMemory :指定显示内存字节数。此实际行为是特定于平台的;在OS上 X 10.8,这使用二进制样式,但这可能会随着时间而改变。
NSByteCountFormatterCountStyleDecimal :显式指定KB的字节数,1000字节显示为1 KB
NSByteCountFormatterCountStyleBinary :显式指定KB的字节数,1024字节显示为1 KB
答案 1 :(得分: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);
}
答案 2 :(得分: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]);
}
}
}
以下是测试数据:
{ 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" }