I have never had consistent success with unpack. It seems like it works
once, but never again. here is a pretty stripped down example of reading
from a simple binary file with a simple unpacking. PLEASE let me know what
my stupid error is, because I have been hammering my Perl CD bookshelf and
can't figure it out.
The unpack() is working fine - it's read() that's causing problems. The fourth parameter to read() specifies the offset at which the data will be placed in the target variable - *not* the offset it will be read from in the file.
while (read SOURCE, $buffer, 1, $index)
Here you're reading one byte into $buffer, at position $index within $buffer. If $buffer is not large enough to contain $index+1 characters, it automagically grows to fit.
my @chars = unpack "C", $buffer;
Here you're unpacking one unsigned character from $buffer - i.e. the first byte. The first time through the loop, this gets the correct value, because $buffer at that point contains only one byte. After that, however, the byte just read appears at $index within $buffer, and all of the bytes prior to that are zero.
It appears that what you want is to read and unpack a byte at a specific offset within a file. To do that you need to use seek(), like this:
#!/usr/bin/perl -w
use strict; use Carp; use Data::Dumper; use Fcntl ':seek';
my $source_path = shift; my $len = -s $source_path; open SOURCE, "<:raw", $source_path or die "screaming:$!";
my $buffer = ""; my $index = 0; while ($index < $len) { seek SOURCE, $index, SEEK_SET; read SOURCE, $buffer, 1; my @chars = unpack "C", $buffer; print Dumper([EMAIL PROTECTED]); print Dumper(\$buffer); $index++; }
Note that the format string in unpack() can also take a numeric value following the type specifier. You could use that to slurp the file up and unpack it into an array of byte values all in one go:
#!/usr/bin/perl -w
use strict; use Carp; use Data::Dumper;
my $source_path = shift; my $len = -s $source_path; open SOURCE, "<:raw", $source_path or die "screaming:$!";
my $buffer = ""; read SOURCE, $buffer, $len; my @chars = unpack "C$len", $buffer; print Dumper([EMAIL PROTECTED]); print Dumper(\$buffer);
sherm--