解码Perl中的3字节整数

时间:2013-03-19 23:13:52

标签: perl unpack

我正在读取一个二进制文件格式,该格式以4个常量校验字节开头,后跟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,除了十六进制编码和其他愚蠢的追求。

4 个答案:

答案 0 :(得分: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 :(得分: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");

答案 2 :(得分:1)

不,unpack不支持3字节(或任意长度)整数,但你可以使用无符号的16位big-endian int来节省一些工作:

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

答案 3 :(得分: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