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.