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バイト)
私たちが達成したいのは次のとおりです。
Pack()を使用して、これらのフィールドをバイナリ文字列にパッケージ化します。
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);
または、リモートデコードからデータをロードします。