PHPでは、 Pack()関数は、特定の形式でデータをバイナリ文字列にパッケージ化するための非常に強力なツールです。多くの場合、ネットワーク送信、ファイルの書き込み、またはバイナリプロトコルとの対話に使用されます。それに対応して、 unpack()関数は、パッケージ化されたバイナリ文字列を構造化データに戻すことができます。この記事では、パック()とunpack()を使用してカスタム構造のパッケージと解析を実現する方法を詳細に紹介し、特定の例を通じてアプリケーションをよりよく理解するのに役立ちます。
Pack()関数は、形式の文字列に基づいて1つ以上のデータをバイナリ文字列にパッケージ化します。一般的な形式は次のとおりです。
A :nul塗りつぶされた文字列(文字列固定長)
A :スペース塗りつぶされた文字列(文字列固定長)
C :署名されていない文字(1バイト)
C :署名された文字(1バイト)
S :署名されていない短い整数(2バイト)
S :署名された短い整数(2バイト)
L :符号なしの長い(4バイト)
L :署名された長い整数(4バイト)
N :署名されていない長い整数(4バイト、ネットワークのエンディアンネス)
N :署名されていない短い整数(2バイト、ネットワークのエンディアンネス)
次のような単純な構造定義があるとします。
ユーザーID(符号なしの長い整数、4バイト)
ステータス(署名されていない文字、1バイト)
バランス(署名された短い整数、2バイト)
名前(固定長さ10バイト文字列)
これらのデータをpack()でパッケージ化し、 uppack()で解析する方法は?
<?php
// データを定義します
$userId = 123456789;
$status = 1;
$balance = -250;
$name = "チャン・サン";
// 使用pack()パッケージングデータ
// 形式の説明:
// N - ユーザーID,ネットワークのエンディアンネスの署名されていない長い整数(4バイト)
// C - 州,署名されていない文字(1バイト)
// s - バランス,署名された短い整数(2バイト)
// a10 - 名前,固定長10バイト,NUL充填
$packedData = pack('NCsa10', $userId, $status, $balance, $name);
// パッケージ化されたバイナリデータの16進表現を印刷します,観察しやすい
echo "パックされたデータ(16進): " . bin2hex($packedData) . PHP_EOL;
// ネットワークを介したデータ送信をシミュレートします,受け取った後、開梱します
$unpackedData = unpack('NuserId/Cstatus/sbalance/a10name', $packedData);
// 未払いの配列を印刷します
print_r($unpackedData);
?>
パックされたデータ(16進): 075bcd1501ff06e58f5a696e67
Array
(
[userId] => 123456789
[status] => 1
[balance] => -250
[name] => チャン・サン
)
N形式は、署名されていない長い整数(4バイト)を表し、ネットワークバイト順序(Big Endian)を採用します。これは、クロスプラットフォームデータ送信によく使用され、一貫したバイト順序を確保します。
Cは、ステータスフィールドの符号なし文字、1バイトを意味します。
Sは署名された短い整数(2バイト)を表し、バランスは負で、署名された値がサポートされます。
A10は固定長の文字列を表します。文字列が不十分な場合、 \ 0で満たされます。
uppack()関数は同じ形式の文字列を介してデータを開梱し、連想配列を返し、キー名をカスタマイズして各フィールドへのアクセスを容易にすることができます。
バイトオーダーの問題<br> データを異なるマシンアーキテクチャ間で送信する必要がある場合は、小さな端と小さな端の間の互換性を確保するために、ネットワークEndian( n 、 n )形式を使用することをお勧めします。
弦のパディング<br> Aフォーマットを使用すると、文字列の不十分な部分が\ 0で記入されますが、 Aはスペースに記入します。解析エラーを避けるために、適切な充填方法を選択してください。
固定データの長さ<br> パッケージング形式は、開梱形式と厳密に一致する必要があります。特に、文字列の長さは同じでなければなりません。そうしないと、データの解析はエラーを引き起こします。
デバッグスキル<BR> bin2hex()を使用してバイナリデータを16進数に変換して、デバッグと検証を容易にすることができます。
URLフィールドを含むデータパケットをパッケージ化する必要があり、ドメイン名の部分をM66.netに置き換える必要がある場合は、最初に文字列を処理してからパッケージ化できます。