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
    [baz] => o
)
配列
(
    [foo] => foobarbaz
    [バー] =>
    [バズ] =>
)

NULL バイトは常にそこにあることに注意してください。これは で確認できますhexdump

期待される結果

配列
(
    [フー] => フー
    [バー] => バー
    [バズ] => バズ
)

ノート

explode同様の結果を得るために使用できることを知っています。私は代替案を求めているのではなく、aフォーマット文字の背後にあるロジックを理解したいだけです(ドキュメントが言うように「NULで埋められた文字列」)。

「NULL」値は、これらすべてにどこで関与しますか?

4

1 に答える 1

6

元の答え

「「NULL」値は、これらすべてにどこで関与するのでしょうか?」

どこにもない。

PHP pack()/unpack() のドキュメントを更新する必要があると確信しています。基本的に、NULL で終了する文字列を参照している箇所はどこでも、ドキュメントは Perl バージョンのコードから取られたものであり、PHP で何が起こっているかを反映したものではありません。

基本的に、Perl には C スタイルの文字列があり、これを null で終了して、文字列の末尾がどこにあるかを知ることができます。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」

おそらく、あなたが思っていることをしていないでしょう。NULL 文字がないため、foo + bar の間、および bar + baz の間の文字列に「NULL」文字を入れていません。代わりに、文字 '0' を配置しています。これはたまたまほとんどの文字セットで出力されませんが、文字として特別な意味はありません。

アンパックの代わりに爆発を使用することについて言及したことは知っていますが、文字列の長さがわかっている場合は、次を使用できます。

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

わかりやすくするために追加

サイラスは次のように書いています。

「NULL バイト」とは、値が 0 のバイトを意味します。

「foo\x00bar\x00baz」という文字列がどこにあるのかわかりませんが、

i) ゼロで表される NULL 文字をサポートする言語からのものでなければなりません。PHP は NULL 文字をサポートしていません。pack("A*A*A*", "foo", "bar", "baz"); ゼロを含む文字列は生成されません。

ii) PHP バージョンの unpack は NULL 文字をサポートしておらず (PHP は NULL 文字をサポートしていないため)、16 進値 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 である最初の 3 文字を抽出します。次に、0x0、0x62、0x61 の次の 3 文字を抽出します。最後に、値 0x72、0x0、0x62 を抽出します。

于 2012-07-24T13:55:10.567 に答える