Converting NSNumber (bytes) to megabytes

Discussion in 'Mac Programming' started by pcwiz, Jul 30, 2009.

  1. macrumors member

    Joined:
    May 28, 2008
    #1
    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
     
  2. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    It's just division:
    MB = bytes / (1024*1024)
    GB = bytes / (1024*1024*1024)
     
  3. thread starter macrumors member

    Joined:
    May 28, 2008
    #3
    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?
     
  4. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #4
    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.)
     
  5. thread starter macrumors member

    Joined:
    May 28, 2008
    #5
    [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 :)
     
  6. macrumors 6502

    Cinder6

    Joined:
    Jul 9, 2009
    #6
    [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).
     
  7. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #7
    No, it returns an unsigned long long. objectForKey:NSFileSize returns an NSNumber object that contains the unsigned long long.

    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?

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

    Cinder6

    Joined:
    Jul 9, 2009
    #8
    Ah, makes sense.
     
  9. macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #9
    I thought it was %llu as it is unsigned.
     
  10. thread starter macrumors member

    Joined:
    May 28, 2008
    #10
    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
     
  11. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #11
    Yep, you are right.
     

Share This Page