On Feb 6, 2004, at 3:58 PM, Thane wrote:

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--



Reply via email to