objective-c - mac - reducir zoom safari
¿Clase ObjC/Cocoa para convertir el tamaño a una secuencia legible por humanos? (8)
¿Hay una manera simple de hacer algo como ...
[NSMagicDataConverter humanStringWithBytes:20000000]
..que devolvería "19.1MB"?
A partir de OS X 10.8 e iOS 6, puede usar NSByteCountFormatter .
Tu ejemplo sería este:
[NSByteCountFormatter stringFromByteCount:20000000 countStyle:NSByteCountFormatterCountStyleFile];
Aquí está mi propia opinión sobre el problema:
enum {
kUnitStringBinaryUnits = 1 << 0,
kUnitStringOSNativeUnits = 1 << 1,
kUnitStringLocalizedFormat = 1 << 2
};
NSString* unitStringFromBytes(double bytes, uint8_t flags){
static const char units[] = { ''/0'', ''k'', ''M'', ''G'', ''T'', ''P'', ''E'', ''Z'', ''Y'' };
static int maxUnits = sizeof units - 1;
int multiplier = (flags & kUnitStringOSNativeUnits && !leopardOrGreater() || flags & kUnitStringBinaryUnits) ? 1024 : 1000;
int exponent = 0;
while (bytes >= multiplier && exponent < maxUnits) {
bytes /= multiplier;
exponent++;
}
NSNumberFormatter* formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setMaximumFractionDigits:2];
if (flags & kUnitStringLocalizedFormat) {
[formatter setNumberStyle: NSNumberFormatterDecimalStyle];
}
// Beware of reusing this format string. -[NSString stringWithFormat] ignores /0, *printf does not.
return [NSString stringWithFormat:@"%@ %cB", [formatter stringFromNumber: [NSNumber numberWithDouble: bytes]], units[exponent]];
}
Por defecto (si se pasa 0
para flags
), se generarán unidades SI (base diez). Puede configurar kUnitStringBinaryUnits
para seleccionar unidades binarias (base dos) adecuadas para la memoria, o kUnitStringOSNativeUnits
para que el tipo de unidad se seleccione automáticamente en función de la versión del sistema operativo (pre-Leopard obtiene la base dos, después-Leopard obtiene la base diez). El establecimiento de kUnitStringLocalizedFormat
formatea la cadena en función de la configuración regional actual del usuario. Por ejemplo:
unitStringFromBytes(1073741824, 0); // → "1.07 GB"
unitStringFromBytes(1073741824, kUnitStringBinaryUnits); // → "1 GB"
unitStringFromBytes(1073741824, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "1.07 GB" (In Mac OS 10.6)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12,345.68 YB" (In Mac OS 10.6, in the US)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12.345,68 YB" (In Mac OS 10.6, in Spain)
Aquí está la función de ayuda necesaria para las unidades nativas del sistema operativo:
BOOL leopardOrGreater(){
static BOOL alreadyComputedOS = NO;
static BOOL leopardOrGreater = NO;
if (!alreadyComputedOS) {
SInt32 majorVersion, minorVersion;
Gestalt(gestaltSystemVersionMajor, &majorVersion);
Gestalt(gestaltSystemVersionMinor, &minorVersion);
leopardOrGreater = ((majorVersion == 10 && minorVersion >= 5) || majorVersion > 10);
alreadyComputedOS = YES;
}
return leopardOrGreater;
}
Aquí hay una función similar a Objective C (usa NSNumber, NSArray, NSStirng, etc ...) para hacer esta conversión.
Esto se basa en la respuesta de Sidnicious, así que muchas gracias por el trabajo inicial realizado allí. También basado en artículos de Wikipedia.
Úselo generalmente así: [HumanReadableDataSizeHelper humanReadableSizeFromBytes:[NSNumber numberWithDouble:doubleValue]]
.
Pero, parece que quiere unidades SI con un multiplicador 1024, así que lo usaría así: [HumanReadableDataSizeHelper humanReadableSizeFromBytes:[NSNumber numberWithDouble:doubleValue] useSiPrefixes:YES useSiMultiplier:NO]
La razón por la que prefijo a los prefijos binarios (ki, Mi) es porque esos parecen ser el prefijo de unidad más apropiado configurado para usar para tamaños de datos en una computadora. Lo que solicitó fueron los prefijos de la unidad SI pero usando un multiplicador de 1024, técnicamente incorrecto. Aunque señalaré que los prefijos SI para múltiplos de 1024 son bastante comunes y los prefijos binarios no son bien aceptados (según Wikipedia).
HumanReadableDataSizeHelper.h
@interface HumanReadableDataSizeHelper : NSObject
/**
@brief Produces a string containing the largest appropriate units and the new fractional value.
@param sizeInBytes The value to convert in bytes.
This function converts the bytes value to a value in the greatest units that produces a value >= 1 and returns the new value and units as a string.
The magnitude multiplier used is 1024 and the prefixes used are the binary prefixes (ki, Mi, ...).
*/
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes;
/**
@brief Produces a string containing the largest appropriate units and the new fractional value.
@param sizeInBytes The value to convert in bytes.
@param useSiPrefixes Controls what prefix-set is used.
@param useSiMultiplier Controls what magnitude multiplier is used.
This function converts the bytes value to a value in the greatest units that produces a value >= 1 and returns the new value and units as a string.
When useSiPrefixes is true, the prefixes used are the SI unit prefixes (k, M, ...).
When useSiPrefixes is false, the prefixes used are the binary prefixes (ki, Mi, ...).
When useSiMultiplier is true, the magnitude multiplier used is 1000
When useSiMultiplier is false, the magnitude multiplier used is 1024.
*/
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes useSiPrefixes:(BOOL)useSiPrefixes useSiMultiplier:(BOOL)useSiMultiplier;
@end
HumanReadableDataSizeHelper.m
@implementation HumanReadableDataSizeHelper
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes
{
return [self humanReadableSizeFromBytes:sizeInBytes useSiPrefixes:NO useSiMultiplier:NO];
}
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes useSiPrefixes:(BOOL)useSiPrefixes useSiMultiplier:(BOOL)useSiMultiplier
{
NSString *unitSymbol = @"B";
NSInteger multiplier;
NSArray *prefixes;
if (useSiPrefixes)
{
/* SI prefixes
http://en.wikipedia.org/wiki/Kilo-
kilobyte (kB) 10^3
megabyte (MB) 10^6
gigabyte (GB) 10^9
terabyte (TB) 10^12
petabyte (PB) 10^15
exabyte (EB) 10^18
zettabyte (ZB) 10^21
yottabyte (YB) 10^24
*/
prefixes = [NSArray arrayWithObjects: @"", @"k", @"M", @"G", @"T", @"P", @"E", @"Z", @"Y", nil];
}
else
{
/* Binary prefixes
http://en.wikipedia.org/wiki/Binary_prefix
kibibyte (KiB) 2^10 = 1.024 * 10^3
mebibyte (MiB) 2^20 ≈ 1.049 * 10^6
gibibyte (GiB) 2^30 ≈ 1.074 * 10^9
tebibyte (TiB) 2^40 ≈ 1.100 * 10^12
pebibyte (PiB) 2^50 ≈ 1.126 * 10^15
exbibyte (EiB) 2^60 ≈ 1.153 * 10^18
zebibyte (ZiB) 2^70 ≈ 1.181 * 10^21
yobibyte (YiB) 2^80 ≈ 1.209 * 10^24
*/
prefixes = [NSArray arrayWithObjects: @"", @"ki", @"Mi", @"Gi", @"Ti", @"Pi", @"Ei", @"Zi", @"Yi", nil];
}
if (useSiMultiplier)
{
multiplier = 1000;
}
else
{
multiplier = 1024;
}
NSInteger exponent = 0;
double size = [sizeInBytes doubleValue];
while ( (size >= multiplier) && (exponent < [prefixes count]) )
{
size /= multiplier;
exponent++;
}
NSNumberFormatter* formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setMaximumFractionDigits:2];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle]; // Uses localized number formats.
NSString *sizeInUnits = [formatter stringFromNumber:[NSNumber numberWithDouble:size]];
return [NSString stringWithFormat:@"%@ %@%@", sizeInUnits, [prefixes objectAtIndex:exponent], unitSymbol];
}
@end
Me gustaría meter esto en una subclase NSFormatter.
#import <Foundation/Foundation.h>
@interface SOFileSizeFormatter : NSNumberFormatter
{
@private
BOOL useBaseTenUnits;
}
/** Flag signaling whether to calculate file size in binary units (1024) or base ten units (1000). Default is binary units. */
@property (nonatomic, readwrite, assign, getter=isUsingBaseTenUnits) BOOL useBaseTenUnits;
@end
static const char sUnits[] = { ''/0'', ''K'', ''M'', ''G'', ''T'', ''P'', ''E'', ''Z'', ''Y'' };
static int sMaxUnits = sizeof sUnits - 1;
@implementation SOFileSizeFormatter
@synthesize useBaseTenUnits;
- (NSString *) stringFromNumber:(NSNumber *)number
{
int multiplier = useBaseTenUnits ? 1000 : 1024;
int exponent = 0;
double bytes = [number doubleValue];
while ((bytes >= multiplier) && (exponent < sMaxUnits)) {
bytes /= multiplier;
exponent++;
}
return [NSString stringWithFormat:@"%@ %cB", [super stringFromNumber: [NSNumber numberWithDouble: bytes]], sUnits[exponent]];
}
@end
Uso:
NSString *path = ...; // path to a file of 1,500,000 bytes
NSString *sizeString = nil;
NSNumber *sizeAttrib = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:NULL]objectForKey:NSFileSize];
SOFileSizeFormatter *sizeFormatter = [[[SOFileSizeFormatter alloc] init] autorelease];
[sizeFormatter setMaximumFractionDigits:2];
sizeString = [sizeFormatter stringFromNumber:sizeAttrib];
// sizeString ==> @"1.43 MB"
[sizeFormatter setUseBaseTenUnits:YES];
sizeString = [sizeFormatter stringFromNumber:sizeAttrib];
// sizeString ==> @"1.5 MB"
Puede usar FormatterKit y su clase TTTUnitOfInformationFormatter
:
https://github.com/mattt/FormatterKit
También está disponible a través de CocoaPods con:
pod ''FormatterKit'', ''~> 1.1.1''
Sé que las preguntas son para Obj C pero si alguien está buscando una versión rápida:
public static func fileSizeDisplay(fromBytes:Int) -> String {
let display = ["bytes","KB","MB","GB","TB","PB"]
var value:Double = Double(fromBytes)
var type = 0
while (value > 1024){
value /= 1024
type = type + 1
}
return "/(String(format:"%g", value)) /(display[type])"
}
- (id)transformedValue:(id)value
{
double convertedValue = [value doubleValue];
int multiplyFactor = 0;
NSArray *tokens = @[@"bytes",@"KB",@"MB",@"GB",@"TB"];
while (convertedValue > 1024) {
convertedValue /= 1024;
multiplyFactor++;
}
return [NSString stringWithFormat:@"%4.2f %@",convertedValue, tokens[multiplyFactor]];
}
NSString *stringFromFileSize(NSInteger theSize)
{
/*
From http://snippets.dzone.com/posts/show/3038 with slight modification
*/
float floatSize = theSize;
if (theSize<1023)
return([NSString stringWithFormat:@"%i bytes",theSize]);
floatSize = floatSize / 1024;
if (floatSize<1023)
return([NSString stringWithFormat:@"%1.1f KB",floatSize]);
floatSize = floatSize / 1024;
if (floatSize<1023)
return([NSString stringWithFormat:@"%1.1f MB",floatSize]);
floatSize = floatSize / 1024;
return([NSString stringWithFormat:@"%1.1f GB",floatSize]);
}