在 Perl 中解码 3 字节整数

Posted

技术标签:

【中文标题】在 Perl 中解码 3 字节整数【英文标题】:Decoding 3-byte integer in Perl 【发布时间】:2013-03-19 23:13:52 【问题描述】:

我正在读取一个二进制文件格式,它以 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 除了十六进制编码和其他业余爱好外,我并没有使用太多。

【问题讨论】:

【参考方案1】:

您可以在字符串中插入一个空字节,以便能够使用“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;

【讨论】:

【参考方案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");

【讨论】:

【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

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

【讨论】:

酷。如果我需要更好的表现,我会把它放在我的后兜里——不过可能会让下一个人(可能是我未来的自己)感到困惑。

以上是关于在 Perl 中解码 3 字节整数的主要内容,如果未能解决你的问题,请参考以下文章

使用 perl 在 MIME 中解码附件时出错

编码解码--三种常见字符编码简介:ASCIIUnicode和UTF-8

SyntaxError :( unicode错误)'unicodeescape'编解码器无法解码位置2-3的字节:截断 UXXXXXXXX转义[重复]

'utf8'编解码器在python中解码('utf-8')时无法解码字节0xc3

Java - MP3 解码并将其存储到字节数组中

读取 csv 文件时出错(unicode 错误)“unicodeescape”编解码器无法解码位置 2-3 中的字节:截断 \UXXXXXXXX 转义 [重复]