【问题标题】:Decoding 3-byte integer in Perl在 Perl 中解码 3 字节整数
【发布时间】: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 除了十六进制编码和其他业余爱好外,我并没有使用太多。

【问题讨论】:

    标签: perl unpack


    【解决方案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
          

          【讨论】:

          • 酷。如果我需要更好的表现,我会把它放在我的后兜里——不过可能会让下一个人(可能是我未来的自己)感到困惑。
          猜你喜欢
          • 1970-01-01
          • 2019-10-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-24
          • 1970-01-01
          • 2016-01-10
          相关资源
          最近更新 更多