使用Perl pack函数H2模板打包超5字节时数据损坏问题咨询
Perl pack('H2') 处理多字节数据时最后一字节损坏的问题
你的问题核心是pack模板与参数类型不匹配:
H2模板的作用是把十六进制字符串(比如"11")打包成对应二进制字节,它接收的参数必须是字符串类型的十六进制字符。- 但你通过
map {hex($_)} @b得到的@c是十进制数值(比如hex("11")返回十进制的17),用H2模板打包数值属于错误用法。
前五个字节看似正确只是巧合——前几个十六进制字符串转成十进制后,数值的十进制字符串恰好和原十六进制字符有某种巧合的对应,但这完全是不可靠的。
解决方法
有两种靠谱的实现方式:
方法1:直接处理十六进制字符串(更简洁)
先去掉字符串中的冒号,用 H* 模板一次性打包整个十六进制字符串:
my $a = "11:22:33:44:55:66"; $a =~ s/://g; # 去掉冒号得到 "112233445566" my $d = pack('H*', $a); my @e = unpack('H2'x6, $d); foreach (@e) { printf("%02x:", $_); }
方法2:用 C 模板打包十进制字节值
如果需要保留分字节处理的逻辑,C 模板专门用来把十进制字节值(0-255)打包成二进制字节:
my $a = "11:22:33:44:55:66"; my @b = split /:/, $a; my @c = map {hex($_)} @b; # 得到十进制字节值(17, 34, 51, 68, 85, 102) my $d = pack('C*', @c); # 用C*打包所有字节 my @e = unpack('H2'x6, $d); foreach (@e) { printf("%02x:", $_); }
运行任意一种代码,都能得到预期输出:11:22:33:44:55:66:
关于你得到 0a 的原因
你的最后一个参数是 102(hex("66") 的结果),Perl 会把数值 102 转成十进制字符串 "102",H2 模板仅取前两个字符 "10",将其视为十六进制字符串转成二进制字节。不同环境下的字符串处理细节可能导致最终输出为 0a,但本质都是模板与参数不匹配导致的错误。
内容的提问来源于stack exchange,提问作者AliA
相关产品推荐
相关产品推荐

