
1arryb
User
Feb 23, 2009, 12:01 PM
Post #7 of 16
(20180 views)
|
Re: [FishMonger] Digest::MD5::digest woes
[In reply to]
|
Can't Post
|
|
Hi FishMonger, First of all, thanks a lot for replying! Now, onto the meat of your comments: 1. Cleaner test code. Ok, I'll try to do better in future posts. 2. use warnings - yes, good idea. 3. my $IN vs *IN, cool, but irrelevant. 4. use binmode. Agree, safer. Turns out to be Irrelevant for linux/cygwin though. 5. seek to file start before recalculating. Yes, it works, but it implies that Digest::MD5 needs to read all of the bytes for each call to *digest(). That's fine for passwords, but not so good for calculating the digest of large file contents, as I'm doing. I guess the bottom line is that I (naively, as it turns out) thought that Digest::MD5 was caching the digest (or content) at addfile() then using the cached representation for subsequent calls to *digest(). I will recode accordingly. Perhaps something like this:
#!/usr/bin/perl use strict; use warnings; use Digest::MD5; # Calculate the md5 sum for a file. # Note, $d and $s are references to the returned binary and hex string digests, respectively. # sub getFileDigest { my ($f, $d, $s) = @_; open (my $fh, "<$f") or return -1; binmode($fh); my $md5 = Digest::MD5->new; $md5->addfile($fh); $$d = $md5->digest; # Don't use hexdigest() after digest(). $$s = ''; map { $$s .= sprintf("%02x", $_) } (unpack("C*", $$d)); close($fh); return 0; } my $file = $ARGV[0]; my ($digest, $digestStr) = ''; if ( getFileDigest($file, \$digest, \$digestStr) ) { print "Oops! getFileDigest() failed.\n"; } else { # Reference MD5. my $tStr = `md5sum $file`; $tStr =~ tr/\r\n//d; $tStr =~ s/ .*//; print "md5sum: $tStr\n"; # Digest::MD5->digest, converted to a string inside the function. print "hexdigest: $digestStr\n"; # Same as the above, just checking that the binary digest made it # back to the main program ok. $tStr = ''; map { $tStr .= sprintf("%02x", $_) } (unpack("C*", $digest)); print "digest: $tStr\n"; }
|