如何从Perl中的二进制文件中读取无符号整型值?

问题描述:

比方说,我有一个被格式化像如何从Perl中的二进制文件中读取无符号整型值?

[unsigned int(length of text)][text][unsigned int(length of text)][text][unsigned int(length of text)][text] 

一个二进制文件和文件只是不断重复这一模式。如何读取unsigned int并在Perl中打印出文本块?

此外,这是一个二进制文件,而不是纯文本文件。

这是一个小的工作示例。

#!/usr/bin/perl 

use strict; 
use warnings; 

my $INT_SIZE = 2; 
my $filename = 'somefile.bin'; 

open my $fh, '<', $filename or die "Couldn't open file $filename: $!\n"; 

binmode $fh; 

while (read $fh, my $packed_length, $INT_SIZE) { 

    my $text = ''; 
    my $length = unpack 'v', $packed_length; 

    read $fh, $text, $length; 

    print $length, "\t", $text, "\n"; 
} 

变化INT_SIZE和解包模板的尺寸和字节顺序,以适应(无论是“V”或“N”或“V”或“N”)。有关更多详细信息,请参见unpack联机帮助页。

您需要在数据上使用unpack函数。退房Pack/Unpack Tutorial (aka How the System Stores Data)

这应该让你在正确的方向前进(假设32位):

#!/usr/bin/perl 

use strict; 

my $strBuf = "perl rocks"; 
my $packed = pack("I Z15", length($strBuf), $strBuf); 
{ 
    open(my $binFile, '>', "test.bin") || die("Error opening file\n"); 
    binmode $binFile; 
    print $binFile $packed; 
    close $binFile; 
} 


open(my $binFile, '<', "test.bin") || die("Error opening file\n"); 
binmode $binFile; 

my $buffer; 
read($binFile, $buffer, 4); ## Read out unsigned int binary data 
my $length = unpack("I", $buffer); ## Unpack the data 

read($binFile, $buffer, $length); ## Read the length out as binary 
my $string = unpack("Z$length", $buffer); ## Unpack the string data in buffer 

print "Len: $length String: $string\n"; 
exit; 
+1

你的代码假定C中的一个'unsigned int'是4个字节,但不能保证是这种情况(正如我所知道的那样)。避免混淆的一种更好的方法是读入整个文件并_then_处理它,这样如果代码在16位平台上运行,其中'unsigned int'是两个字节,那么代码就可以正常工作。 – 2009-09-02 21:37:45

+0

这就是为什么我说我假设32位。我同意,读入内存是一个很好的,可以说是更好的解决方案,但我们不知道正在处理的文件的大小或计算机上可用的内存大小。这两种解决方案都有陷阱。 – 2009-09-02 21:43:14

+0

Chris,如何将整个文件读入内存避免使用错误的整数大小? – 2009-09-03 02:37:13

除了使用unpack,作为RC所指出的,你几乎肯定会想用readsysread读取数据从文件中。

+0

他编辑了他的答案。 – 2009-09-02 21:38:31

这里没有足够的信息来完全解决这个问题。

需要的是长度字段和文本字段的确切格式。是2个字节,4个字节还是8个字节? (都可能。)也是小端或大端?

给出此信息,然后使用读取函数访问第一个整数,并使用位操作或解压缩函数将其转换为数字。

下一个问题是文本字符串的确切格式。它是ASCII,EBCDIC还是UTF格式?知道这一点,您可以计算字符串的长度,并使用一个或多个读取操作来获取原始字符串,您可能必须将其转换为更易于管理的形式。

另一件事 - 你需要以二进制模式打开文件,否则你可能无法获得预期的结果。

+0

我认为这是他平台的默认'unsigned int',它有一个'unpack'代码,这样你就可以依赖这样的平台依赖。而且你可能很懒,只需在整个文件中阅读,然后在阅读完成后再进行处理。 – 2009-09-02 20:58:47