現在の位置: ホーム> 最新記事一覧> カスタム構造のパッケージングと解析の例:pack() + unpack()

カスタム構造のパッケージングと解析の例:pack() + unpack()

M66 2025-05-31

PHPでは、 Pack()関数は、特定の形式でデータをバイナリ文字列にパッケージ化するための非常に強力なツールです。多くの場合、ネットワーク送信、ファイルの書き込み、またはバイナリプロトコルとの対話に使用されます。それに対応して、 unpack()関数は、パッケージ化されたバイナリ文字列を構造化データに戻すことができます。この記事では、パック()unpack()を使用してカスタム構造のパッケージと解析を実現する方法を詳細に紹介し、特定の例を通じてアプリケーションをよりよく理解するのに役立ちます。


Pack()関数の紹介

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()関数は同じ形式の文字列を介してデータを開梱し、連想配列を返し、キー名をカスタマイズして各フィールドへのアクセスを容易にすることができます。


ヒントと予防策

  1. バイトオーダーの問題<br> データを異なるマシンアーキテクチャ間で送信する必要がある場合は、小さな端と小さな端の間の互換性を確保するために、ネットワークEndian( nn )形式を使用することをお勧めします。

  2. 弦のパディング<br> Aフォーマットを使用すると、文字列の不十分な部分が\ 0で記入されますが、 Aはスペースに記入します。解析エラーを避けるために、適切な充填方法を選択してください。

  3. 固定データの長さ<br> パッケージング形式は、開梱形式と厳密に一致する必要があります。特に、文字列の長さは同じでなければなりません。そうしないと、データの解析はエラーを引き起こします。

  4. デバッグスキル<BR> bin2hex()を使用してバイナリデータを16進数に変換して、デバッグと検証を容易にすることができます。


URLシナリオの例と組み合わせて

URLフィールドを含むデータパケットをパッケージ化する必要があり、ドメイン名の部分をM66.netに置き換える必要がある場合は、最初に文字列を処理してからパッケージ化できます。