Подтвердить что ты не робот

Как правильно получить размер файла и преобразовать его в MB, GB в Cocoa?

Возможный дубликат:
ObjC/ Cocoa класс для преобразования размера в удобочитаемую строку?

Я новичок в Cocoa. Я пытаюсь получить размер файлов папок должным образом. И отобразите его в МБ, если он меньше 1 ГБ или в ГБ.

То, как я хочу, чтобы оно отображалось, округляется с одним номером после точки.

Пример 5,5 МБ, если оно больше 1000 > 1,1 ГБ

Я пытаюсь использовать этот

 unsigned  long long size= ([[[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil] fileSize]);

Но я не могу правильно преобразовать число и отображать его, как хочу.

Спасибо.

4b9b3361

Ответ 1

Для преобразования размера файла в 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]];
}

EDIT:

Вы также можете использовать класс NSByteCountFormatter. Доступно в iOS 6.0/OS X версии 10.8 и более поздних версиях.

[NSByteCountFormatter stringFromByteCount:1999 countStyle:NSByteCountFormatterCountStyleFile];

Вы можете использовать NSByteCountFormatterCountStyleFile, NSByteCountFormatterCountStyleMemory, NSByteCountFormatterCountStyleDecimal или NSByteCountFormatterCountStyleBinary в countStyle.

NSByteCountFormatterCountStyleFile. Указывает отображение количества байтов файлов или хранилища. Фактическое поведение для этого конкретная платформа; на OS X 10.8, это использует десятичный стиль, но это могут меняться со временем.

NSByteCountFormatterCountStyleMemory. Указывает отображение количества байтов памяти. Фактическое поведение для этого зависит от платформы; по ОС X 10.8, это использует двоичный стиль, но со временем может измениться.

NSByteCountFormatterCountStyleDecimal. Указывает количество байтов для КБ явно, 1000 байт показаны как 1 КБ

NSByteCountFormatterCountStyleBinary. Указывает количество байтов для КБ явно, 1024 байта показаны как 1 КБ

Ответ 2

Если вы ориентируетесь на 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);
    }

Ответ 3

Вот фрагмент кода из моей библиотеки. (Таким образом, я освобождаю его под упрощенной лицензией BSD.) Он довольно широко протестирован, и он делает все округление точно правильным. Это не так тривиально, как кажется. Он всегда дает две значимые цифры, если не печатает три цифры (например, 980 B), и в этом случае все три цифры значительны.

Использование stringWithFormat:@"%..something...f" не будет работать, потому что если вы округлите 999999 байт до 1000 килобайт, вы хотите отобразить его как 1,0 МБ, а не 1000 кБ.

Обратите внимание, что этот код также выполняет "округление банкиров" или "непредвзятое округление" или "округление до четного", в зависимости от того, что вы хотите назвать. Таким образом, 1050 становится "1,0 кБ", но 1150 становится "1,2 кБ". Это то же самое, что 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" }