PHP開発では、ネットワーク伝送またはファイルストレージに便利な、指定された形式のバイナリ文字列に複数のデータをパッケージ化する必要がある場合があります。 PHPが提供するパック関数はこの要件を達成できますが、複雑な形式の文字列を渡す必要があり、さまざまなシナリオの形式は大きく異なります。この記事では、パック関数を使用して、複数の形式をサポートしてコードの再利用性と柔軟性を向上させる一般的なパッケージング機能をカプセル化する方法を紹介します。
パック関数の基本的な構文は次のとおりです。
string pack(string $format, mixed ...$values)
$フォーマットは、 cなどの形式を指定します。Cは署名されていない文字を表し、 nは16ビットのビッグエンディアンエンディアン整数などを表します。
$値は、対応する形式のデータです。
たとえば、2つの署名されていないキャラクターと16ビットのビッグエンディアン整数をパッケージ化します。
$data = pack('CCn', 0x01, 0x02, 0x1234);
カプセル化する機能:
フォーマット文字列と対応する値の配列を受け入れます。
フォーマット文字列に従って、自動的にパッケージを1つずつパッケージします。
一般的な形式タイプをサポートし、拡張に便利です。
パラメーターの不一致と形式のエラーを処理します。
機能の署名:
function universalPack(string $format, array $values): string
以下は、 C 、 N 、 N 、 Aなどをサポートする基本的な実装です。形式:
function universalPack(string $format, array $values): string {
$result = '';
$formatLength = strlen($format);
$valueIndex = 0;
for ($i = 0; $i < $formatLength; $i++) {
$char = $format[$i];
$repeat = 1;
// 重複があるかどうかを検出します,のようにa4、C2待って
if (isset($format[$i + 1]) && ctype_digit($format[$i + 1])) {
$repeat = (int)$format[$i + 1];
$i++;
}
for ($r = 0; $r < $repeat; $r++) {
if (!isset($values[$valueIndex])) {
throw new InvalidArgumentException("値の数は形式と一致しません");
}
$value = $values[$valueIndex];
$valueIndex++;
switch ($char) {
case 'C': // 署名されていない文字
$result .= pack('C', $value);
break;
case 'n': // 16ビットビッグエンディアンバイトオーダー
$result .= pack('n', $value);
break;
case 'N': // 32ビットビッグエンディアンバイトオーダー
$result .= pack('N', $value);
break;
case 'a': // NUL文字列を入力します,長さrepeat決める
if ($repeat < 1) {
throw new InvalidArgumentException("a形式は長さで指定する必要があります");
}
$str = str_pad(substr($value, 0, $repeat), $repeat, "\0");
$result .= $str;
// aすべての処理を一度にフォーマットしますrepeat,valueIndex増分なし
$valueIndex--;
break;
default:
throw new InvalidArgumentException("サポートされていないフォーマット文字: $char");
}
}
}
return $result;
}
データパケットをパッケージ化するとしますが、構造は次のとおりです。
1バイトコマンド番号( c )
2バイトデータ長( n )
4バイトデータID( n )
10バイトデータコンテンツ(String、 A10 )
コール例:
$command = 0x01;
$length = 14;
$dataId = 123456;
$content = "hello";
$packed = universalPack('CnNa10', [$command, $length, $dataId, $content]);
echo bin2hex($packed);
出力は次のとおりです。
01000e0001e24068656c6c6f0000000000
パック関数は非常に強力ですが、形式と値は直接使用するとエラーが発生しやすくなります。
ユニバーサルユニバーサルパック関数をカプセル化して、マルチフォーマットデータのパッケージを簡素化します。
機能は、より多くのフォーマットをサポートしたり、小規模な秩序をサポートするなど、実際のニーズに応じて強化され続けることができます。
実際のプロジェクトでは、開梱関数を開梱機能と組み合わせて、ピア開梱機能を実現することもできます。