Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

pcwiz

macrumors member
Original poster
May 28, 2008
55
0
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
 
It's just division:
MB = bytes / (1024*1024)
GB = bytes / (1024*1024*1024)
 
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?
 
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.)
 
[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 :)
 
[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).
 
[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.
 
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
Code:
//
//  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
Code:
//  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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.