在 Perl 中将二进制数据拆分为字节数组

Posted

技术标签:

【中文标题】在 Perl 中将二进制数据拆分为字节数组【英文标题】:Split binary data into byte array in Perl 【发布时间】:2012-10-31 13:22:14 【问题描述】:

我基本上想将二进制字符串转换为字节数组/列表(以便允许索引,并避免使用substr,因为它的语法对我来说很复杂),我想出了以下MWE:

#!/usr/bin/env perl

use warnings;
use strict;

# Use open ':raw';      # Unknown PerlIO layer class ':raw'
use open IO => ':raw';

binmode(STDIN);
binmode(STDOUT);

# Create original 8-bit byte array/list
my @atmp = (0x80, 0x23, 0x14, 0x0d, 0x0a, 0x00, 0x00, 0x80, 0x43, 0x00, 0x00);

# Make a copy of portion
my @atmp2 = (0) x 2;
@atmp2[0..1] = @atmp[7..8];

# Print output
print "Copied atmp2 contents as hex: " . join(", ", unpack("H2"x2, pack("C"x2,@atmp2))) . "\n";
print "Copied atmp2 as ushort (16bit) int: " . unpack("S", pack("C"x2, @atmp2));
# doublecheck value by routing through printf with format specifier:
printf(" [%d]\n", unpack("S", pack("C"x2, @atmp2)));


# Now, the same data as string:
my $indata = "\x80\x23\x14\x0d\x0a\x00\x00\x80\x43\x00\x00";

# Create byte array (by converting string $indata to array/list with `split`)
my @btmp = split('',$indata);
print "lastindex: " . $#btmp . "\n";

# Make a copy of portion
my @btmp2 = (0) x 2;
@btmp2[0..1] = @btmp[7..8];

# Print output
print "Copied btmp2 contents as hex: " . join(", ", unpack("H2"x2, pack("C"x2,@btmp2))) . "\n";
print "Copied btmp2 as ushort (16bit) int: " . unpack("S", pack("C"x2, @btmp2));
# doublecheck value by routing through printf with format specifier:
printf(" [%d]\n", unpack("S", pack("C"x2, @btmp2)));

运行此代码的结果是:

$ perl test.pl
Copied atmp2 contents as hex: 80, 43
Copied atmp2 as ushort (16bit) int: 17280 [17280]
lastindex: 10
Argument "M-\0" isn't numeric in pack at test.pl line 38.
Argument "C" isn't numeric in pack at test.pl line 38.
Copied btmp2 contents as hex: 00, 00
Copied btmp2 as ushort (16bit) int: 0 [0]

如何让第二部分 (btmp2) 的行为与第一部分 (atmp2) 相同?

【问题讨论】:

【参考方案1】:

事实证明,当使用split 时,它确实创建了一个与原始字符串中的字节相同的数组;但是,它似乎也以某种方式将结果数组标记为“文本”,因此进一步处理失败并显示“参数不是数字”。

答案是将split 行替换为使用unpack 的行,而不是:

- my @btmp = split('',$indata);
+ my @btmp = unpack('C*',$indata);

... 之后,一切都按预期工作(两个打印输出相同)。有趣的是,在这两种情况下,“lastindex”(对于从字符串派生的数组)都将显示为 10(这让我觉得binmode 可能有问题,这就是为什么所有这些语句都在代码中) .

【讨论】:

它确实帮助了我,谢谢!我不敢相信回答这个简单的问题有多么困难,但我找不到一个 Perl 文档、手册页或教程可以清楚地解释这一点......

以上是关于在 Perl 中将二进制数据拆分为字节数组的主要内容,如果未能解决你的问题,请参考以下文章

在 JavaScript 中将字节解释为打包的二进制数据

在 Python 3 中将二进制字符串转换为字节数组

如何在Java中将字节数组转换为十六进制格式

如何在 C++ 中将字节数组转换为十六进制字符串?

在 C++ 中将十六进制字符串转换为字节数组

如何在 C 中将字节数组转换为十六进制字符串?