PHPでは、 Pack()関数を使用して、指定された形式のバイナリ文字列にデータをパッケージ化します。多くの開発者は、ネットワークプロトコルまたはバイナリファイルを扱うときに使用します。 pack( "n"、12345)は典型的な使用法です。つまり、整数12345は、大規模なバイト順(ネットワークバイト順序)で4バイトのバイナリ文字列にパッケージ化されます。
しかし、 Pack( "n"、12345)を使用した後に得られる結果は、予想される出力と矛盾していることに気付くことがあり、16進または出力に変換すると「奇妙」に見えます。なぜこれがなぜですか?この記事は、その背後にある原則を分析するのに役立ちます。
フォーマット文字「n」はpack()で表されます。
N :署名の長いロング(4バイト、32ビットの符号なし整数)
ビッグエンディアン、つまり、高いバイトが正面にあり、低いバイトが背面にあります
たとえば、整数12345の16進表現は0x3039であり、それに対応する4バイトのBig-Endianは次のとおりです。
00 00 30 39
したがって、 Pack( "n"、12345)によって生成されたバイナリ文字列は、これらの4バイトに16進数に変換する必要があります。
多くの人々は、結果が「間違っているように見える」ことを観察し、一般的な理由は次のとおりです。
多くの目に見えない文字を含むブラウザまたは端末にバイナリ文字列を直接出力するか、いくつかのバイトはコントロール文字に解析されます。
バイナリ結果は、16進数やBase64などの読み取り可能な形式に変換されません。
結果の期待は、実際の意味とは一致しません。たとえば、 pack( "n"、12345)が数値文字列「12345」を直接出力すると考えています。
次のPHPコードを書くとします。
<?php
$binary = pack("N", 12345);
echo bin2hex($binary);
?>
操作の結果は次のとおりです。
00003039
これは、予想される4バイトのビッグエンディアンの結果です。
echo $ binaryを使用する場合。 $ binaryは通常のテキストではなく、バイナリデータであるため、文字化けしたコードまたは空白が表示されます。
エラーデモンストレーション:
<?php
echo pack("N", 12345);
?>
Webページまたは端末に出力すると、文字化けされたコードが表示されないか、表示されない文字が表示されません。これにより、 Pack()の結果が間違っていると誤って考えます。
pack( "n"、12345)は、 12345の数を表す4バイトのバイナリ文字列を大幅なバイト順に返します。
結果は、文字列「12345」ではなく、バイナリデータになります。
結果を表示するときは、 bin2hex()または同様の方法を使用して読み取り可能な形式に変換することをお勧めします。
バイナリの直接出力は、一見「奇妙な」結果をもたらす可能性がありますが、エラーではありません。
<?php
// 番号を入れます12345詰め込まれています4BYTE Big-Endianバイナリ
$binary = pack("N", 12345);
// バイナリの16進表現を示しています,便利な観察
echo "Hex representation: " . bin2hex($binary) . "\n";
// 使用することもできます unpack 抑制防止
$unpacked = unpack("N", $binary);
echo "Unpacked number: " . $unpacked[1] . "\n";
?>
実行後の出力:
Hex representation: 00003039
Unpacked number: 12345
パックに関するPHP公式ドキュメント
バイナリデータ処理のためのEndianの重要性を理解します
ネットワークプロトコルとバイナリデータの関係