web-dev-qa-db-fra.com

Comment obtenir correctement la taille du fichier et le convertir en Mo, Go en Cocoa?

Duplicata possible:
classe ObjC/Cocoa pour convertir la taille en chaîne lisible par l'homme?

Je suis nouveau à Cocoa. J'essaie d'obtenir correctement la taille des fichiers de dossiers. Et affichez-le en Mo s'il est inférieur à 1 Go, ou en Go.

La façon dont je veux l'afficher est arrondie avec un chiffre après le point.

Exemple 5,5 Mo si elle est supérieure à 1000> 1,1 Go

J'essaye d'utiliser ça

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

Mais je ne peux pas convertir correctement le nombre et l'afficher comme je le souhaite.

Merci.

43
User1234

Pour convertir la taille du fichier en Mo, Gb utilise la fonction ci-dessous

- (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]];
}

ÉDITER:

Vous pouvez également utiliser la classe NSByteCountFormatter . Disponible dans iOS 6.0/OS X v10.8 et versions ultérieures.

[NSByteCountFormatter stringFromByteCount:1999 countStyle:NSByteCountFormatterCountStyleFile];

Vous pouvez utiliser NSByteCountFormatterCountStyleFile, NSByteCountFormatterCountStyleMemory, NSByteCountFormatterCountStyleDecimal ou NSByteCountFormatterCountStyleBinary dans countStyle.

NSByteCountFormatterCountStyleFile : spécifie l'affichage du nombre d'octets de fichier ou de stockage. Le comportement réel pour cela est spécifique à la plate-forme; sous OS X 10.8, cela utilise le style décimal, mais cela peut changer avec le temps.

NSByteCountFormatterCountStyleMemory : spécifie l'affichage du nombre d'octets en mémoire. Le comportement réel pour cela est spécifique à la plate-forme; sous OS X 10.8, cela utilise le style binaire, mais cela peut changer avec le temps.

NSByteCountFormatterCountStyleDecimal : spécifie le nombre d'octets pour Ko de manière explicite, 1000 octets sont affichés comme 1 Ko

NSByteCountFormatterCountStyleBinary : spécifie le nombre d'octets pour Ko de manière explicite, 1024 octets sont affichés comme 1 Ko

115
Parag Bafna

Si vous ciblez OS X 10.8 ou iOS 6, vous pouvez utiliser NSByteCountFormatter .

J'écrirais votre exemple comme ceci:

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

Voici un morceau de code de ma bibliothèque. (Je le publie sous la licence BSD simplifiée donc là.) Il est assez largement testé, et il fait tous les arrondis exactement corrects. Ce n'est pas aussi trivial qu'il y paraît. Il donne toujours deux chiffres significatifs, sauf s'il imprime trois chiffres (par exemple, 980 B), auquel cas les trois chiffres sont significatifs.

En utilisant stringWithFormat:@"%..something...f" ne fonctionnera pas car si vous arrondissez 999999 octets jusqu'à 1 000 kilo-octets, vous voulez l'afficher en 1,0 Mo, et non en 1 000 Ko.

Notez que ce code effectue également "l'arrondi bancaire" ou "l'arrondi non biaisé" ou "l'arrondi à égal", quel que soit le nom que vous souhaitez utiliser. Ainsi, 1050 devient "1,0 kB", mais 1150 devient "1,2 kB". C'est exactement la même manière que printf le fait sur mon système et c'est la méthode d'arrondi généralement préférée pour ce genre de chose.

#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]);
        }
    }
}

Voici les données de test:

{ 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" }
8
Dietrich Epp