2013-03-19 57 views
0

我正在读取一个二进制文件格式,它以4个常量校验字节开始,后面跟着3个八位字节,表示记录的数据部分将会有多长。我可以解码如下:在Perl中解码3字节整数

read($fh, $x, 7) or do { 
    last if eof; 
    die "Can't read: $!"; 
}; 
my ($type, $l1, $l2, $l3) = unpack("a4 C3", $x); 
my $length = $l1 << 16 | $l2 << 8 | $l3; 

是否有更直接的方式来读取该3字节值,没有中间变量?我错过了pack规格中的某些东西?除了十六进制编码和其他一些困难追求之外,我还没有非常使用pack

回答

1

不,unpack不支持3字节(或任意长度)的整数,但你可以使用一个16位无符号大端INT节省一点工作:

my ($type, $l1, $l23) = unpack("a4 Cn", $x); 
my $length = $l1 << 16 | $l23; 
+0

听起来很不错,谢谢。 – 2013-03-20 03:08:27

2

你可以插入空字节到以字符串能够使用“N”格式:

substr($x, 4, 0, "\0"); 
my ($type, $length) = unpack "a4 N", $x; 

编辑:要不解开两个步骤:

my ($type, $length) = unpack "a4 a3", $x; 
$length = unpack "N", "\0" . $length; 
1

解决方案:获取类型的方法很好。但是,我建议您将长度分开解压为一个四字节整数,然后丢弃这四个字节的第一个字节。即使它重叠并丢弃类型的最后一个字节,它也会更有效。

my $type = unpack("a4", $x); 
my $length = unpack("x3N", $x); # skips the first 3 bytes of your original 7-byte string 
$length = $length & 0xFFFFFF; # returns only the last 3 bytes of the four-byte integer 
+0

很酷。如果我需要更好的表现,我会把它放在我的后兜里 - 可能会混淆下一个人(可能是我未来的自我)。 – 2013-03-20 03:07:51

2
my $type = unpack("a4", $x); 
my $len = unpack("N", "\0".substr($x, 4)); 

my ($type, $plen) = unpack("a4 a3", $x); 
my $len = unpack("N", "\0$plen");