我正在读取一个二进制文件格式,该格式以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
,除了十六进制编码和其他愚蠢的追求。
答案 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