PHP 的pack 不支持B* 的格式,但它支持H*。在 Perl 中,您可以使用
sub pack_Bstar {
my($bits) = @_;
my $Hstar;
my $nybble = 0;
for (my $i = 0; $i < length $bits; ++$i) {
$nybble *= 2;
$nybble += int substr($bits, $i, 1);
if ($i % 4 == 3) {
$Hstar .= sprintf "%x", $nybble;
$nybble = 0;
}
}
my $pad = 4 - length($bits) % 4;
if ($pad != 4) {
$nybble = ($nybble << $pad);
$Hstar .= sprintf "%x", $nybble;
}
pack "H*", $Hstar;
}
上面的代码不是惯用的 Perl,但翻译成 PHP 应该很简单。
H* 格式首先需要一个高 nybble(4 位)的十六进制字符串。上面的代码一次咀嚼四个位来计算每个 nybble 值。例如,对于1011的位串,追踪算法给出
- nybble = 0
- nybble = 2 * 0 + 1 = 1
- nybble = 2 * 1 + 0 = 2
- nybble = 2 * 2 + 1 = 5
- nybble = 2 * 5 + 1 = 11
10112确实是1110,也就是b16。如果最后一个 nybble 不完整(在 1 到 3 位之间),我们将该位左移适当的位数。这具有在右侧补零的效果。
测试:
my @tests = (
["01001010011101010111001101110100" => "Just"],
["0110000101101110011011110111010001101000011001010111001" => "another"],
["01010000010010000101000000101111010100000110010101110010011011" => "PHP/Perl"],
["01101000011000010110001101101011011001010111001000101100" => "hacker,"],
);
for (@tests) {
my($input,$expect) = @$_;
my $got = pack_Bstar $input;
print "$input: ", ($got eq $expect ? "PASS" : "FAIL"), " ($got)\n";
}
输出:
01001010011101010111001101110100:通过(仅)
0110000101101110011011110111010001101000011001010111001:通过(另一个)
01010000010010000101000000101111010100000110010101110010011011:通过(PHP / Perl)
01101000011000010110001101101011011001010111001000101100:通过(黑客,)