I've got some technical files produced by a scientific device. From time to time, these recorded files get corrupted and we have to do some hexadecimal modification by hand.
I'm wondering how I could automate it. I was thinking of Perl, as I've got some knowledge in that, but even if I manage to read the offset of interest, I don't know how to write the new value.
I've got two things to do:
I've tried to use sysread
and syswrite
on a filehandle, but I can't get through the different steps.
Maybe Perl is not a good option, I don't know how to sort it out.
Here is my actual script:
use warnings;
use strict;
use diagnostics;
use Fcntl qw(:seek);
my($fh, $filename, $byte_position, $byte_value);
$filename = "MYFILE.tac";
$byte_position = 4;
my $filesize = -s $filename;
print "Size: $filesize\n";
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;
Here is the working code based on Ikegami's answer:
#!c:/Perl64/bin/perl.exe
use warnings;
use strict;
use diagnostics;
my $dir = 'MYDIRECTORY';
opendir DIR, $dir or die "cannot open dir $dir: $!";
my @files = glob "$dir/*.tac";
closedir(DIR);
foreach(@files){
my $qfn = $_;
my $file;
{
open(my $fh, '<:raw', $qfn)
or die("Can't open \"$qfn\": $!\n");
local $/;
$file = <$fh>;
}
{
my $packed_length = pack('V', length($file) - 8);
substr($file, 0x0004, length($packed_length), $packed_length);
}
{
my $num_blocks;
++$num_blocks while $file =~ /TRCKfmt/g;
my $packed_num_blocks = pack('V', $num_blocks);
substr($file, 0x005C, length($packed_num_blocks), $packed_num_blocks);
}
{
open(my $fh, '>:raw', $qfn)
or die("Can't create \"$qfn\": $!\n");
print($fh $file);
}
}