简体   繁体   English

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

[英]How do I unpack binary files with Perl?

I have two binary files equal in size, but not in values. 我有两个大小相等但值不相等的二进制文件。 I used unpack as follows, but the results are weird. 我使用了如下的unpack ,但是结果很奇怪。

When I use "big" binary files, both of the outputs shows part of the results: 当我使用“大”二进制文件时,两个输出都显示了部分结果:

One binary file starts good - ends bad, 一个二进制文件从好的开始-从坏的开始

Second binary file goes wrong at the start. 第二个二进制文件在开始时出错。

Where do you think may be the weak point? 您认为哪里可能是薄弱点?

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";

The output is: 输出为:

BIN FILE1 LENGTH: 1203 BIN FILE1长度:1203

BIN FILE2 LENGTH: 124 BIN FILE2长度:124

The input files are: 输入文件是:

-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

If there is another simple and safe way to gather binary files data to an array I'll be glad to know. 如果有另一种简单安全的方式将二进制文件数据收集到数组中,我将很高兴知道。

I suspect that you are not reading the entire file (the <> operator tries to read a record, using the record seperator $/ which is newline by default). 我怀疑您没有读取整个文件( <>运算符尝试使用记录分隔符$ /(默认情况下为换行符)读取记录。 Try changing the read to something like this: 尝试将读取更改为以下内容:

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

You said you had "big" files. 您说您有“大”文件。 It looks like they aren't all that big, and will fit easily in memory. 看起来它们并没有那么大,并且很容易容纳在内存中。

However, if your files are too big to fit in memory all at once you can use read or sysread to read data in chunks. 但是,如果文件太大而无法一次全部容纳在内存中,则可以使用readsysread读取块中的数据。

Example - Read in 4000 bytes at a time: 示例-一次读取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 = '';
}

Use a 3 argument open with lexical handles, it avoids certain security and maintainability issues. 使用带有词法句柄的3参数open ,可以避免某些安全性和可维护性问题。 3 arg open also allows you to specify file encoding in the mode flag. 3 arg open还允许您在模式标志中指定文件编码。 That way you don't need to call binmode. 这样,您无需调用binmode。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM