PDA

View Full Version : Converting NSNumber (bytes) to megabytes




pcwiz
Jul 30, 2009, 12:56 PM
Hi I have the following code:

NSNumber *fs = [[[NSFileManager defaultManager] fileAttributesAtPath:applicationPath traverseLink:NO] objectForKey:NSFileSize];

Which returns the file size in bytes for my file (an NSString called applicationPath). I want to convert this to megabytes, rounded off to 2 decimal places. How would I do this?

Thanks

P.S. Sorry for these basic questions, Im an ObjC newbie



kainjow
Jul 30, 2009, 02:01 PM
It's just division:
MB = bytes / (1024*1024)
GB = bytes / (1024*1024*1024)

pcwiz
Jul 30, 2009, 02:18 PM
Hmm yes, I tried that earlier, but it kept returning a random value. I think the issue is with my method to get the file size. Is there a better way to get file size?

kainjow
Jul 30, 2009, 02:21 PM
Are you calling [fs unsignedLongLongValue] to get the primitive from the NSNumber? Are you converting it to double so you handle the decimal portion? (post your code if you're still having issues.)

pcwiz
Jul 30, 2009, 02:36 PM
[fs unsignedLongLongValue] returns an NSNumber containing the number of bytes. The annoying part is that it seems to return a different value every time for the same file. I have not converted it to a double, but all I need is an easy way to get the size of a file or folder using NSFileManager.

Thanks for your help :)

Cinder6
Jul 30, 2009, 03:10 PM
[fs unsignedLongLongValue] has a return type of unsigned long long, not NSNumber*. Just divide the value returned by unsignedLongLongValue by 0x100000 to get megabytes.

EDIT: I just checked out the class reference for NSFileManager. In one part, it says the object for the key NSFileSize is an NSString, but in another, it says the corresponding value is an NSNumber. If it's the case that it's actually an NSString, you might have to use the NSScanner class (scanLongLong).

kainjow
Jul 30, 2009, 03:32 PM
[fs unsignedLongLongValue] returns an NSNumber containing the number of bytes.
No, it returns an unsigned long long. objectForKey:NSFileSize returns an NSNumber object that contains the unsigned long long.

The annoying part is that it seems to return a different value every time for the same file. I have not converted it to a double, but all I need is an easy way to get the size of a file or folder using NSFileManager.

This (AFAIK) only works on files. You have to go through a folder's files and subfolders recursively to calculate the folder size. That's another topic and there's plenty of code out there to do that for you :)

As for the "random" value... how are you checking this? Logging it to the console? If so, are you using the right format specifier, %lld?

EDIT: I just checked out the class reference for NSFileManager. In one part, it says the object for the key NSFileSize is an NSString, but in another, it says the corresponding value is an NSNumber. If it's the case that it's actually an NSString, you might have to use the NSScanner class (scanLongLong).

NSFileSize is defined as an NSString because it's a key to a dictionary. The object it returns from the dictionary is an NSNumber.

Cinder6
Jul 30, 2009, 04:49 PM
NSFileSize is defined as an NSString because it's a key to a dictionary. The object it returns from the dictionary is an NSNumber.

Ah, makes sense.

jared_kipe
Jul 30, 2009, 06:14 PM
As for the "random" value... how are you checking this? Logging it to the console? If so, are you using the right format specifier, %lld?



I thought it was %llu as it is unsigned.

pcwiz
Jul 30, 2009, 06:37 PM
Hey guys,

I succeeded in creating a working custom class to deal with these file size operations. Here are the .h and .m files, they work fine and build with no warnings/errors but if there are any issues please by all means correct me:

FileSize.h
//
// FileSize.h
// Created by PCWiz on 30/07/09.
//

#import <Cocoa/Cocoa.h>


@interface FileSize : NSObject {

}
// This method converts a given # of bytes into human readable format (KB, MB, GB)
- (NSString *)stringFromFileSize:(int)theSize;
// Returns the size of a file in bytes
- (int)sizeOfFile:(NSString *)path;
// Returns the size of a folder in bytes
- (int)sizeOfFolder:(NSString *)path;
@end

FileSize.m

// FileSize.m
// Created by PCWiz on 30/07/09.

#import "FileSize.h"


@implementation FileSize
- (NSString *)stringFromFileSize:(int)theSize
{
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]);
}

- (int)sizeOfFile:(NSString *)path
{
NSDictionary *fattrib = [[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES];
int fileSize = (int)[fattrib fileSize];
return fileSize;
}

- (int)sizeOfFolder:(NSString*)folderPath
{
NSArray *contents;
NSEnumerator *enumerator;
NSString *path;
contents = [[NSFileManager defaultManager] subpathsAtPath:folderPath];
enumerator = [contents objectEnumerator];
int fileSizeInt = 0;
while (path = [enumerator nextObject]) {
NSDictionary *fattrib = [[NSFileManager defaultManager] fileAttributesAtPath:[folderPath stringByAppendingPathComponent:path] traverseLink:YES];
fileSizeInt +=[fattrib fileSize];
}
return fileSizeInt;
}
@end

kainjow
Jul 30, 2009, 09:12 PM
I thought it was %llu as it is unsigned.

Yep, you are right.