这里唯一真正的困难是确保输入和输出文件都以二进制模式读取。这可以通过在:raw
打开文件时使用 PerlIO 层来实现。
这个程序似乎做你想做的事。它首先定位索引块并将其读入字符串,然后打开该字符串以供输入,并读取每个组成文件的开始和结束位置以及名称。此后处理每个文件很简单。
请注意,除非索引块的格式比您说的更严格,否则您只能依赖每行上的第一个、第二个和最后一个空格分隔的字段,因为随机文本可能包含空格。也无法指定包含空格的文件名。
使用 的输出Data::Dump
是为了演示正确的功能,而不是程序运行所必需的。
use v5.10;
use warnings;
use Fcntl ':seek';
use autodie qw/ open read seek close /;
open my $fh, '<:raw', 'container.bin';
read $fh, my $index_loc, 6;
seek $fh, $index_loc, SEEK_SET;
read $fh, my ($index), 1024;
my %contents;
open my $idx, '<', \$index;
while (<$idx>) {
my @fields = split;
next unless @fields;
$contents{$fields[-1]} = [ $fields[0], $fields[1] ];
}
use Data::Dump;
dd \%contents;
for my $file (keys %contents) {
my ($start, $end) = @{ $contents{$file} };
my $size = $end - $start;
seek $fh, $start, SEEK_SET;
my $nbytes = read $fh, my ($data), $size;
die "Premature EOF" unless $nbytes == $size;
open my $out, '>:raw', $file;
print { $out } $data;
close $out;
}
输出
{
"Capture.PNG" => [6, 15149],
"index.php" => [15149, 15168],
"untilted.tga" => [15168, 211794],
}