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.
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
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);
}
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" }