Reputation: 163
I have a binary file that I need to be able to parse through. I'm looking to specify an offset and then have the program return the byte value at that location.
I'm not sure about how to go about this. I've got the file open part, but I don't know how to get the program to jump to the location.
Upvotes: 2
Views: 3925
Reputation: 139711
Use seek
and the handy constants from the Fcntl module as in
#! /usr/bin/env perl
use bytes;
use strict;
use warnings;
use Fcntl ':seek';
open my $fh, "<", $0 or die "$0: open: $!";
seek $fh, 0, SEEK_END or die "$0: seek: $!";
my $last = tell $fh;
die "$0: tell: $!" if $last < 0;
for (1 .. 20) {
my $offset = int rand($last + 1);
seek $fh, $offset, SEEK_SET or die "$0: seek: $!";
defined read $fh, my $byte, 1 or die "$0: read: $!";
$byte = "\\$byte" if $byte eq "'" || $byte eq "\\";
printf "offset %*d: \\x%02x%s\n",
length $last, $offset,
unpack("C", $byte),
$byte =~ /[[:print:]]/a ? " '$byte'" : "";
}
__DATA__
π« π²π πΏπππ πππ π―π π·πππππππ π«
πππ²π½ : πππ’π₯π‘ππ¨π© β: π πΏππ¨ππ§ππ©π ππππ€π’π’ππ£πππ©ππ€π£π¨
π
πΉ π πΈ π π π π π π π π π π π
π© πΈ π€ π€ π¦ π π πΉ π£ π π π π π π π€ π€ π©
π Β‘Ζ¨dlΙΙ₯ Ζ¨α΄Ι₯Κ ΙdoΙ₯ puΙ Κ»Ξ»Ιp ΙΙα΄u Ι ΙΚΙΙ₯ Κ»ΚΙnl pooβ
π
Sample output:
offset 47: \x65 'e' offset 392: \x20 ' ' offset 704: \xf0 offset 427: \x5c '\'' offset 524: \x61 'a' offset 1088: \x75 'u' offset 413: \x20 ' ' offset 1093: \xbb offset 1112: \xc9 offset 377: \x24 '$' offset 64: \x46 'F' offset 361: \x62 'b' offset 898: \xf0 offset 566: \x5d ']' offset 843: \xf0 offset 1075: \xc9 offset 280: \x20 ' ' offset 3: \x2f '/' offset 673: \x8a offset 153: \x20 ' '
The contents of the __DATA__
section were borrowed from Tomβs excellent suggestions for dealing with UTF-8 in Perl programs.
Upvotes: 2
Reputation: 80443
use Fcntl qw(:seek);
my($fh, $filename, $byte_position, $byte_value);
$filename = "/some/file/name/goes/here";
$byte_position = 42;
open($fh, "<", $filename)
|| die "can't open $filename: $!";
binmode($fh)
|| die "can't binmode $filename";
sysseek($fh, $byte_position, SEEK_CUR) # NB: 0-based
|| die "couldn't see to byte $byte_position in $filename: $!";
sysread($fh, $byte_value, 1) == 1
|| die "couldn't read byte from $filename: $!";
printf "read byte with ordinal value %#02x at position %d\n",
ord($byte_value), $byte_position;
Upvotes: 5