Re: problem with applying md5 to data
Re: problem with applying md5 to data
- Subject: Re: problem with applying md5 to data
- From: Quincey Morris <email@hidden>
- Date: Wed, 29 Jun 2011 01:13:39 -0700
On Jun 29, 2011, at 00:27, Quincey Morris wrote:
>> [fileData appendData:[file readDataOfLength:CHUNK_SIZE]];
>> [file seekToFileOffset:MAX(0, fileSize - CHUNK_SIZE)];
>> [fileData appendData:[file readDataOfLength:CHUNK_SIZE]];
>>
>> [file closeFile];
>
> This is not the worst way to read the entire contents of a file into a NSData object, but it's pretty bad. :)
>
> It would be far easier and more efficient to use [NSData dataWithContentsOfFile: path options: NSDataReadingMapped | NSDataReadingUncached error: NULL];
Er, two things.
I didn't notice until after I posted that you weren't reading the whole file. So, sorry, "pretty bad" was too strong -- I'm upgrading my response to "not the best". :)
I think the way I suggested is still the best way, because (typically) using the NSDataReadingMapped means the file contents are mapped into virtual memory, so pages (4KB, or whatever the VM page size is) are not actually read until you try to access them.
If you use CC_MD5_Init/Update (first part)/Update (last part)/Final instead of the convenience method that does it all, only the parts of the file you need will actually be read.
NSDataReadingMapped is in general the most efficient way to read a file when you only need to read any part once, I think.
The problem with NSFileHandle is that it pretty much sucks as a class. It doesn't return any errors, so if something goes wrong it's either going to throw an exception or just ignore it. IIRC it has no API contract regarding error reporting.
Second thing...
I forgot to point out that your code has a glaring bug. With your declarations, 'fileSize - CHUNK_SIZE' in 'MAX(0, fileSize - CHUNK_SIZE)' is an unsigned expression. It can't go negative, and so that statement isn't doing what it looks like it's doing.
One more thing ...
Since you have no release/retain calls, I'm assuming you're using garbage collection. If that's the case, then this line is very, very dangerous:
> return [SMEncodingUtilities md5HexDigestFromChar:[fileData bytes] withLength:(unsigned int)[fileData length]];
You're passing an *interior* pointer to fileData's private storage, but the (compiler-optimized) lifetime of 'fileData' ends *before* the md5 method is entered, and so the object is subject to being collected *before* you've used the pointer. This will crash.
In your code, the window of danger is pretty small. But it will crash eventually.
The solution is to put a reference to the object after the call:
> NSString* result = [SMEncodingUtilities md5HexDigestFromChar:[fileData bytes] withLength:(unsigned int)[fileData length]];
> [fileData self];
> return result;
It's a PITA, but you gotta be careful with NSData.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden