6

测试

$x = sprintf( "foo\x00bar\x00baz" );
$y = unpack( 'afoo/abar/abaz' , $x );
print_r( $y );
$x = sprintf( "foo\x00bar\x00baz" );
$y = unpack( 'a*foo/a*bar/a*baz' , $x );
print_r( $y );

结果

大批
(
    [foo] => f
    [酒吧] => o
    [巴兹] => o
)
大批
(
    [foo] => foobarbaz
    [酒吧] =>
    [巴兹] =>
)

请注意,NULL 字节始终存在,您可以使用hexdump.

预期结果

大批
(
    [foo] => 富
    [酒吧] => 酒吧
    [巴兹] => 巴兹
)

笔记

我知道我可以用它explode来实现类似的结果。我不是在问替代方案,我只是想了解a格式字符背后的逻辑(如文档所说的“NUL-padded string”)。

“NULL”值在哪里涉及到这一切?

4

1 回答 1

6

原始答案

““NULL”值在哪里涉及到这一切?”

无处。

我很确定 PHP pack()/unpack() 的文档需要更新。基本上,无论您在哪里看到它指的是一个以 NULL 结尾的字符串,该文档都是取自 Perl 版本的代码,而不是 PHP 中发生的事情的反映。

基本上 Perl 有 C 风格的字符串,可以空终止,让您知道字符串的结尾在哪里。在 PHP 中没有 NULL 字符的概念。例如

$test1 = "Test".NULL."ing";
$test2 = "Testing";

if(strcmp($test1, $test2) == 0){
    echo "The strings are the same";
}
else{
    echo "They are different.";
}

将打印“字符串相同”。

顺便说一句:“foo\x00bar\x00baz”

可能没有做你认为它正在做的事情。它没有在 foo + bar 之间和 bar + baz 之间的字符串中放置“NULL”字符,因为没有 NULL 字符。相反,它放置了字符“0”,它恰好没有在大多数字符集中打印出来,但作为字符没有特殊含义。

我知道您提到使用 explode 而不是 unpack 但如果您知道字符串长度,那么您可以使用:

unpack( 'a3foo/a3bar/a3baz' , $binarydata);

为清楚起见添加

赛勒斯写道:

“NULL byte”是指值为 0 的字节:

我不确定你从哪里得到字符串 "foo\x00bar\x00baz" 但是:

i) 它必须来自支持由零表示的 NULL 字符的语言。PHP 不支持 NULL 字符,如果你调用 pack("A*A*A*", "foo", "bar", "baz"); 它不会生成其中包含零的字符串。

ii) PHP 版本的 unpack 不支持 NULL 字符(因为 PHP 不支持 NULL 字符)并将十六进制值为 0 的字符视为另一个字符。例如

function strToHex($string){
    $hex='';
    for ($i=0; $i < strlen($string); $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return $hex;
}

$binarydata = "foo\x00bar\x00baz";

echo "binarydata is ";

var_dump($binarydata);
$y = unpack( 'a3foo/a3bar/a3baz' , $binarydata);
var_dump( $y );

echo strToHex($y['foo'])."\r\n";
echo strToHex($y['bar'])."\r\n";
echo strToHex($y['baz'])."\r\n";

将输出:

binarydata is string(11) "foobarbaz"
array(3) {
  ["foo"]=>
  string(3) "foo"
  ["bar"]=>
  string(3) "ba"
  ["baz"]=>
  string(3) "rb"
}
666f6f
06261
72062

即,它提取值 0x66、0x6f、0x6f 的前三个字符。然后它提取接下来的三个字符,即 0x0、0x62、0x61。最后,它提取值 0x72、0x0、0x62。

于 2012-07-24T13:55:10.567 回答