如何使用Perl解压缩二进制文件?

时间:2009-12-27 17:11:39

标签: perl

我有两个大小相等的二进制文件,但没有值。我使用unpack如下,但结果很奇怪。

当我使用“大”二进制文件时,两个输出都显示部分结果:

一个二进制文件开始很好 - 结束不好,

第二个二进制文件在开始时出错。

你认为哪里可能是弱点?

open(BIN_FILE1, "<bin_files/BINF1.bin") or die("Cannot open file for writing");
open(BIN_FILE2, "<bin_files/BINF2.bin") or die("Cannot open file for writing");
binmode(BIN_FILE1);
binmode(BIN_FILE2);
# N An unsigned long (32-bit) in "network" (big-endian) order.
my @values_tmp1 =  unpack("N*", <BIN_FILE1>);
my @values_tmp2 =  unpack("N*", <BIN_FILE2>);
close (BIN_FILE1);
close (BIN_FILE2);
my $tmp_bin1 = @values_tmp1;
my $tmp_bin2 = @values_tmp2;
print "\nBIN FILE1 LENGTH: ",$tmp_bin1,"\n";
print "\nBIN FILE2 LENGTH: ",$tmp_bin2,"\n";

输出结果为:

  

BIN FILE1 LENGTH:1203

     

BIN FILE2 LENGTH:124

输入文件为:

-rw-rw-r-- 1 yodar yodar   9600 2009-12-23 19:59 BINF1.bin
-rw-rw-r-- 1 yodar yodar   9600 2009-12-27 16:38 BINF2.bin

如果有另一种简单而安全的方法将二进制文件数据收集到数组中,我将很高兴知道。

2 个答案:

答案 0 :(得分:9)

我怀疑你没有读取整个文件(<>运算符尝试使用记录分隔符$ /默认为换行符读取记录)。尝试将读取更改为以下内容:

{
    # Enable slurp mode
    local $/;
    my @values_tmp1 =  unpack("N*", <BIN_FILE1>);
    my @values_tmp2 =  unpack("N*", <BIN_FILE2>);
}

答案 1 :(得分:6)

你说你有“大”文件。看起来它们并不是那么大,并且很容易适应记忆。

但是,如果您的文件太大而无法一次性存储在内存中,则可以使用readsysread来读取数据块中的数据。

示例 - 一次读入4000个字节:

my $file_path = 'bin_files/BINF1.bin';

open my $fh, '<:encoding(raw)', $file_path 
    or die "Cannot open file '$file_path' for reading";

my $buffer;
while ( my $got = read( $fh, $buffer, 4000 ) ) {

  warn "Read $got bytes from file\n."

  my @integers = unpack "N*", $buffer;

  do_stuff( \@integers );

  $buffer = '';
}

使用带有词法句柄的3参数open,它可以避免某些安全性和可维护性问题。 3 arg open还允许您在mode标志中指定文件编码。这样你就不需要调用binmode了。