現在の位置: ホーム> 最新記事一覧> pack()とunpack()を使用して、双方向コンバーターを実装します

pack()とunpack()を使用して、双方向コンバーターを実装します

M66 2025-05-28

PHPでは、 pack()unpack()は、バイナリデータと人間が読み取る形式の間を変換するためによく使用される強力な関数のペアです。この記事では、これらの2つの機能を使用して、ファイルストレージ、ネットワーク伝送、その他のシナリオに適したデータ構造のシリアル化と脱滑りを実現するために、簡単な双方向データコンバーターを作成する方法を説明します。

基本概念

  • pack() :指定された形式に従って、1つ以上の値をバイナリ文字列にパックします。

  • unpack() :指定された形式でバイナリ文字列から値を解析します。

これら2つの関数の形式コードは、整数、浮動小数点タイプ、文字列などの複数のデータ型をサポートしています。一般的な形式文字は次のとおりです。

フォーマット文字意味バイトを占有します
c署名されていないchar 1バイト
n署名されていない短い整数(ビッグエンディアン) 2バイト
n署名の長い(ビッグエンディアン) 4バイト
a nul fill string nバイト

シナリオ設定:単純なデータ構造

次の構造のデータをパッケージ化して解凍する必要があるとします。

  • ユーザーID(4バイト符号なし整数)

  • ユーザーレベル(1バイト)

  • アクティブ化するかどうか(ブール値、0と1で表される)

  • ユーザー名(固定長さの文字列、20バイト)

私たちが達成したいのは次のとおりです。

  1. Pack()を使用して、これらのフィールドをバイナリ文字列にパッケージ化します。

  2. unpack()を使用して、この文字列から元のデータを再分類します。

コンバータークラスを作成します

class DataConverter {
    const FORMAT = 'Nid/Clevel/Cactive/a20username';

    public static function encode($data) {
        return pack(
            self::FORMAT,
            $data['id'],
            $data['level'],
            $data['active'] ? 1 : 0,
            $data['username']
        );
    }

    public static function decode($binary) {
        $result = unpack(self::FORMAT, $binary);
        $result['active'] = $result['active'] === 1;
        $result['username'] = rtrim($result['username'], "\0"); // 取り除く NUL 充填
        return $result;
    }
}

使用の例

$data = [
    'id' => 123456,
    'level' => 5,
    'active' => true,
    'username' => 'm66user'
];

$binary = DataConverter::encode($data);
echo bin2hex($binary) . PHP_EOL;

$parsed = DataConverter::decode($binary);
print_r($parsed);

出力の例(16進表現):

 0001e24005016d363675736572000000000000000000000000
Array
(
    [id] => 123456
    [level] => 5
    [active] => 1
    [username] => m66user
)

アプリケーションシナリオ拡張

このコンバーターは簡単ですが、より複雑な使用シナリオに拡張できます。

  • ソケット通信データの構築や解析などのネットワークプロトコルパケット。

  • バイナリファイルのシリアル化と降下。

  • コンパクトデータストレージ(キャッシュ、埋め込みデバイスなど)が必要な場合に使用されます。

たとえば、エンコードされたデータをリモートインターフェイスに送信できます。

 file_put_contents("https://m66.net/api/upload", $binary);

または、リモートデコードからデータをロードします。