Perl中的字节序列



我有一个数组,数组中的每一项都是由2个数字组成的数组,其值在16位范围内。
对于数组中的每个项目,我需要将这2个数字放入32位整数中,然后将其保存在MySQL数据库中varbinary类型列的表中。

我认为我需要使用pack与模板S!创建一个32位整数,其中包含上/下16位的其他2个数字。
我认为我需要使用pack与模板I!来创建要保存在数据库中的最终值。
但是我不确定如何用pack做到这一点,而且我真的不理解文档中关于如何形成循环的示例。

my( $ip, $cs,
$flags,$fl,$fh,
$ax,$al,$ah, $bx,$bl,$bh, $cx,$cl,$ch, $dx,$dl,$dh, 
$si, $di, $bp, $ds, $es ) =
unpack( 'v2' . ('vXXCC' x 5) . 'v5', $frame );

有人可以帮助我如何使用pack来实现这一点吗?或者pack不是这两种情况的正确解决方案?

例如,创建一个32位的数字,代码片段如下:

my $number1 = 120;
my $number2 = 3090;
my $word = pack( 'S!*S!*', $number1, $number2 );
print "$word n";  

prints:x

我期望它会打印1个数字(32位整数)。我在这里做错了什么?

@ikegami注释后更新:

  1. 32位整数
  2. $number1是高阶位
  3. Big endian

@ikegami注释后更新2.我尝试了以下操作:

my @array = (
[120, 3090],
[34, 2018],
[47, 4005],
[98, 2345],
[111, 1]
);
my @packed;
foreach ( @array ) {
my @elem = $_;
print $elem[0][0]. " - ". $elem[0][1]. "n";
my $id = $elem[0][0];
my $num = $elem[0][1];
my $word = pack( 'S>2', $id, $num);
push @packed, $word;
say sprintf "%v02X", $word;
}
my $packed_output = pack('I*', @packed); // line 63
say sprintf "%v02X", $packed_output;

如果输出如下命令,则失败:

00.78.0C.12
120 - 3090
00.78.0C.12
34 - 2018
00.22.07.E2
47 - 4005
00.2F.0F.A5
98 - 2345
00.62.09.29
111 - 1
00.6F.00.01
Argument "xf^R" isn't numeric in pack at line 63.
Argument ""^G?" isn't numeric in pack at  line 63.
Argument "/^O?" isn't numeric in pack at  line 63.
Argument "b^I)" isn't numeric in pack at  line 63.
Argument "o^A" isn't numeric in pack at line 63.
00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00

关闭

*没有意义。S!*S!*应为S!*S!S!S!2

S!错误。这指的是unsigned int,它至少是16位,但它可以变化。你想要的正好是16位,所以应该是S

您也没有指定字节顺序。因为你想要大结束的字节顺序,你实际上需要S>(或n)。

my $packed = pack( "S>2", $number1, $number2 );  # "x00x78x0Cx12"
say sprintf "%v02X", $packed;  # 00.78.0C.12

可以看到,这会生成一个四个字节的字符串,而不是一个数字。但这就是你想要的。VARBINARY用于存储字节序列。使用usingL>解包字节串得到32位的数字。

这会显示另一个选项。您也可以计算32位的数字并打包。

my $packed = pack( "L>", $number1 << 16 | $number2 );  # "x00x78x0Cx12"
say sprintf "%v02X", $packed;  # 00.78.0C.12

参考:装箱开箱号格式

最新更新