Perl pack()函数和Php的“B”格式字符

时间:2013-03-07 14:37:25

标签: php perl pack

"B"在Perl代码的pack语句中做了什么?

$hce_hash=pack('B*', $hce_hash);

PHP中是否有等效函数?

3 个答案:

答案 0 :(得分:2)

pack 'B*', $s返回由01字符串表示的字节,这些字符构成$s中的字符串。如果需要,$s的值用零填充到可被8整除的长度。

例如,

pack 'B*', '0100101000110101'

结果

chr(0b01001010) . chr(0b00110101);

答案 1 :(得分:2)

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的位串,跟踪算法给出

  1. nybble = 0
  2. nybble = 2 * 0 + 1 = 1
  3. nybble = 2 * 1 + 0 = 2
  4. nybble = 2 * 2 + 1 = 5
  5. nybble = 2 * 5 + 1 = 11
  6. 1011 2 确实是11 10 ,其是b 16 。如果最后一个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: PASS (Just)
    0110000101101110011011110111010001101000011001010111001: PASS (another)
    01010000010010000101000000101111010100000110010101110010011011: PASS (PHP/Perl)
    01101000011000010110001101101011011001010111001000101100: PASS (hacker,)

答案 2 :(得分:2)

正如其他人所说,PHP的pack()不支持B模板,该模板在Perl的pack()中转换为一个位串,表示为0和{的文字字符串{1}}字符,为每字节8位的压缩字节字符串。

但是,由于PHP的pack()确实支持1模板,除了十六进制数字而不是位数之外,我们可以通过首先使用{{3}来模拟PHP中的Perl H模板。将这些位转换为十六进制数字然后打包:

B

(我们不能只将整个输入字符串提供给base_convert()的原因是它将其中间结果存储为PHP浮点数,因此对于数字太大而无法准确表示的数字不会产生正确的结果但是,一次做一个十六进制数字工作正常。)