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.
perldoc -f seek