Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 用于将大小转换为人类可读字符串的ObjC/Cocoa类?_Objective C_Cocoa - Fatal编程技术网

Objective c 用于将大小转换为人类可读字符串的ObjC/Cocoa类?

Objective c 用于将大小转换为人类可读字符串的ObjC/Cocoa类?,objective-c,cocoa,Objective C,Cocoa,有没有一个简单的方法来做类似的事情 [NSMagicDataConverter humanStringWithBytes:20000000] …将返回“19.1MB”?NSString*stringFromFileSize(NSInteger theSize) { /* 从…起http://snippets.dzone.com/posts/show/3038 稍加修改 */ 浮动大小=大小; 如果(尺寸以下是我自己对这个问题的看法: enum { kUnitStringBinaryUn

有没有一个简单的方法来做类似的事情

[NSMagicDataConverter humanStringWithBytes:20000000]
…将返回“19.1MB”?

NSString*stringFromFileSize(NSInteger theSize)
{
/*
从…起http://snippets.dzone.com/posts/show/3038 稍加修改
*/
浮动大小=大小;

如果(尺寸以下是我自己对这个问题的看法:

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

以下是操作系统本机单元所需的帮助函数:

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

我会把它混合成一个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

这里有一个更客观的类C函数(使用NSNumber、NSArray、NSStirng等)来进行此转换

这是基于Sidnicious的回答,非常感谢在那里做的初步工作。也是基于维基百科的文章

一般如下使用:
[HumanReadableDataSizeHelper humanReadableSizeFromBytes:[NSNumber numberWithDouble:doubleValue]

但是,看起来您需要具有1024个乘法器的国际单位制,所以您可以这样使用:
[HumanReadableDataSizeHelper humanReadableSizeFromBytes:[NSNumber numberWithDouble:doubleValue]useSiPrefixes:YES useSiMultiplier:NO]

我默认使用二进制前缀(ki,Mi)的原因这是因为这些似乎是计算机上用于数据大小的最合适的单位前缀集。您要求的是SI单位前缀,但使用的是1024的乘法器,从技术上讲是不正确的。尽管我会注意到,1024的倍数的SI前缀相当常见,二进制前缀不被广泛接受(根据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
@implementation HumanReadableDataSizeHelper
+(NSString*)humanReadableSizeFromBytes:(NSNumber*)sizeInBytes
{
return[self-humanReadableSizeFromBytes:sizeInBytes-usesiprefix:NO-useSiMultiplier:NO];
}
+(NSString*)humanReadableSizeFromBytes:(NSNumber*)sizeInBytes useSiPrefixes:(BOOL)useSiPrefixes useSiMultiplier:(BOOL)useSiMultiplier
{
NSString*unitSymbol=@“B”;
NSInteger乘数;
NSArray*前缀;
如果(使用siprefixes)
{
/*SI前缀
http://en.wikipedia.org/wiki/Kilo-
千字节(kB)10^3
兆字节(MB)10^6
千兆字节(GB)10^9
TB(TB)10^12
千兆字节(PB)10^15
EB)10^18
泽塔比特(ZB)10^21
字节(YB)10^24
*/
前缀=[NSArray数组,其对象为:@“@”k“,@”M“,@”G“,@”T“,@”P“,@”E“,@”Z“,@”Y“,nil];
}
其他的
{
/*二进制前缀
http://en.wikipedia.org/wiki/Binary_prefix
KiB字节(KiB)2^10=1.024*10^3
兆字节(MiB)2^20≈ 1.049 * 10^6
吉比特(吉比特)2^30≈ 1.074 * 10^9
泰比特(TiB)2^40≈ 1.100 * 10^12
PEB字节(PiB)2^50≈ 1.126 * 10^15
exbibyte(EiB)2^60≈ 1.153 * 10^18
西比比特(Zibyte)2^70≈ 1.181 * 10^21
双字节(YiB)2^80≈ 1.209 * 10^24
*/
前缀=[NSArray数组,其对象为:@“”、@“ki”、@“Mi”、@“Gi”、@“Ti”、@“Pi”、@“Ei”、@“Zi”、@“Yi”、nil];
}
如果(使用同步钳)
{
乘数=1000;
}
其他的
{
乘数=1024;
}
NSInteger指数=0;
double size=[sizeInBytes doubleValue];
而((大小>=乘数)&&(指数<[前缀计数])
{
大小/=乘数;
指数++;
}
NSNumberFormatter*格式化程序=[[[NSNumberFormatter alloc]init]autorelease];
[格式化程序设置MaximumFractionDigits:2];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];//使用本地化的数字格式。
NSString*sizeInUnits=[formatter stringFromNumber:[NSNumber numberWithDouble:size]];
返回[NSString stringWithFormat:@“%@%@%@”,sizeInUnits[前缀objectAtIndex:exponent],unitSymbol];
}
@结束

从OS X 10.8和iOS 6开始,您可以使用

您的示例如下所示:

[NSByteCountFormatter stringFromByteCount:20000000 countStyle:NSByteCountFormatterCountStyleFile];

您可以使用FormatterKit及其
TTTunitoInformationFormatter
类:

也可通过CocoaPods获得,包括:

pod 'FormatterKit', '~> 1.1.1'

我知道这些问题是针对Obj C的,但如果有人想要swift版本:

 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])"

    }

我建议将'theSize'参数设置为'size_t'类型,这是一个64位整数。在2G字节后,上述方法将失败。请注意,将1024作为基数(而不是1000)不符合人机界面准则,因此,任何使用此代码的应用都可能被应用商店拒绝。格式为do的字符串es不考虑本地化(例如十进制分隔符符号)-如上所述,这应该使用数字格式化程序来完成。我同意,NSInteger不会持有无符号长数字,您会失去对十进制数字的控制。使用NSNumberFormatter更通用,也是更好的总体选择。我这样做了,但只有两种方法:iOS 6.0或iOS中的stringFromSize:&&stringFromSpeed:NSByteCountFormatter后来,OSX 10.8或Lead,使用此格式的唯一缺点是强制使用当前的区域设置。您的代码很好,但是在OSX上,您必须考虑1000个,而不是1024个,因为硬盘制造商,以及取景器,1 GB=1000 MB:-)
[NSByteCountFormatter stringFromByteCount:20000000 countStyle:NSByteCountFormatterCountStyleFile];
pod 'FormatterKit', '~> 1.1.1'
- (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]];
}
 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])"

    }