Perl:将int打包成任意长度的字节串

标签 perl pack

我想在 N 位容器中编码数字并在 UDP 数据包中发送它们。接收者将知道 N,接收者将从恰好 N 位中获取一个数字。(N <= 64)

有些想法是这样的:

sub to56BIT {
     return pack("??", shift);
}

sub to24BIT {
     return pack("??", shift);
}

my $n = 7;
to24BIT($n);

在接收端:

int n = Get_val24(byte_stream, offset);

在 Perl 中有什么方法可以做到这一点吗?

我认为解决方案可能是:

sub packIntN {
        my $int = shift;
        my $length = shift;
        return pack("B" . $length, substr(unpack("B64", pack("Q>", $int)), 64 - $length));
}

但也许还有更优雅的方式。

输入/输出示例: 我们有一个脚本 test.pl:

use strict;
use warnings;

sub to24BIT {
        #???
}

my $n = 7;

print to24BIT($n);

我想要这个:

./test.pl | hexdump -C
00000000  00 00 07                                          |...|
00000003

另一个脚本test2.pl:

use strict;
use warnings;

sub to40BIT {
        #???
}

my $n = 7;

print to40BIT($n);

我想要这个:

./test.pl | hexdump -C
00000000  00 00 00 00 07                                    |.....|
00000005

最佳答案

N 是否总是 8 的整数因子(8、16、24、32、40、48、56、64 之一)?如果是这样,为了提高速度,我建议为每种尺寸编写一个打包器,并使用调度表找到合适的打包器。

sub pack_8bit  {        pack('C',  $_[0])     }
sub pack_16bit {        pack('S>', $_[0])     }
sub pack_24bit { substr(pack('L>', $_[0]), 1) }
sub pack_32bit {        pack('L>', $_[0])     }
sub pack_40bit { substr(pack('Q>', $_[0]), 3) }
sub pack_48bit { substr(pack('Q>', $_[0]), 2) }
sub pack_56bit { substr(pack('Q>', $_[0]), 1) }
sub pack_64bit {        pack('Q>', $_[0])     }

{
   my %packers = (
       8 => \&pack_8bit,   40 => \&pack_40bit,
      16 => \&pack_16bit,  48 => \&pack_48bit,
      24 => \&pack_24bit,  56 => \&pack_56bit,
      32 => \&pack_32bit,  64 => \&pack_64bit,
   );

   sub pack_num {
      my $packer = $packers{$_[0]}
         or die;
      return $packer->($_[1]);
   }

   sub get_packer {
      my $packer = $packers{$_[0]}
         or die;
      return $packer;
   }
}

my $packed = pack_num(40, 7);
  -or-
my $packer = get_packer(40);
my $packed = $packer->(7);

如果您计划将多个数字打包成一个字符串(如 pack('L>*', @nums)),我也会使用这样的调度表,尽管我我不确定 pack_24bitpack_40bitpack_48bitpack_56bit(除了C 溶液)。

关于Perl:将int打包成任意长度的字节串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33065579/

相关文章:

Linux使用 "select: Bad file descriptor"后返回 "cat"错误

java - 使用 Cygwin 中启动的 perl 脚本运行带有 2 个参数的 Java 文件

xml - Perl XML::LibXML 安装失败

perl - 从十六进制字符串中恢复包值

ruby 包和十六进制值

python - 如何使用 binascii 通过打包和解包重新编码 python 字符串?

linux - 在 perl 中停止具有条件的进程

perl - 我如何解决这个与 BioPerl 相关的谜团?

php - 包 ('i' ,1) 总是 4 个字节吗?

perl - 将十六进制字符串转换为二进制