Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】unpack()関数の使い方

unpack関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

unpack関数は、バイナリ文字列からデータを抽出し、指定されたフォーマットに基づいて解釈する関数です。これは主に、ネットワークプロトコルで送受信されるバイナリデータや、バイナリファイルのコンテンツを読み込み、PHPの変数として扱える形式に変換する際に使用されます。

この関数は、最初の引数にデータの構造を定義する「フォーマット文字列」を受け取ります。このフォーマット文字列には、読み込むデータの型(例えば、符号なしバイト、符号付き整数、浮動小数点数など)とそのバイト数、さらにはバイトオーダー(エンディアン)を指定する文字の組み合わせを使用します。2番目の引数には、解釈の対象となるバイナリ文字列を渡します。オプションとして、3番目の引数で、バイナリ文字列のどの位置から解釈を開始するかをオフセットとして指定することも可能です。

unpack関数は、フォーマット文字列に従ってバイナリ文字列を解析し、抽出されたデータを連想配列として返します。配列のキーはフォーマット文字列内で指定した名前、またはデフォルトの数値キーとなります。unpack関数は、バイナリデータをパックするpack関数と対になる機能を提供し、バイナリデータのエンコードとデコードの両方を可能にします。システムエンジニアにとって、低レベルのデータ処理や外部システムとの連携において非常に重要な役割を果たす関数です。

構文(syntax)

1<?php
2
3$binaryString = "\x01\x00"; // 2バイトのバイナリデータ(例: 16ビットの数値 1)
4$format = "s";              // フォーマット文字列(例: 符号付きショート整数)
5
6$unpackedArray = unpack($format, $binaryString);
7
8?>

引数(parameters)

string $format, string $string, int $offset = 0

  • string $format: バイナリ文字列 $string をどのように解釈するかを定義するフォーマット文字列
  • string $string: 展開するバイナリ文字列
  • int $offset = 0: $string のどの位置から展開を開始するかを指定するオフセット値

戻り値(return)

array|false

与えられたフォーマット文字列に基づいて、バイナリデータから値を展開した配列、または失敗した場合は false が返されます。

サンプルコード

PHP unpackでバイナリを配列・変数にする

1<?php
2
3/**
4 * バイナリ文字列からデータを抽出し、それを個別の変数に展開する例。
5 * unpack関数はバイナリデータをPHPの配列に変換し、
6 * extract関数はその配列のキーを元にローカル変数を作成します。
7 *
8 * PHP 8 での unpack 関数の基本的な使用法と、その結果を変数として扱う方法を示します。
9 */
10function demonstrateUnpackAndExtract(): void
11{
12    // pack関数を使って、unpackで処理するためのバイナリ文字列を作成します。
13    // 's' は符号付きショート整数 (16ビット)、'l' は符号付きロング整数 (32ビット) を表します。
14    // 'a*' は残りのバイト全てを文字列として読み込みます。
15    $binaryString = pack('slA*', 12345, 987654321, 'Hello PHP!');
16
17    echo "元のバイナリ文字列の長さ: " . strlen($binaryString) . "バイト\n";
18
19    // unpack関数を使用してバイナリ文字列を連想配列に変換します。
20    // 各フォーマットコードにはキー名を付けています ('short_val', 'long_val', 'message')。
21    // unpackの戻り値はarray|falseなので、エラーチェックも推奨されますが、
22    // この例では成功を前提としています。
23    $unpackedData = unpack('sshort_val/llong_val/A*message', $binaryString);
24
25    if ($unpackedData === false) {
26        echo "unpackに失敗しました。\n";
27        return;
28    }
29
30    echo "\n--- unpack後の配列の内容 ---\n";
31    print_r($unpackedData);
32
33    // extract関数を使って、$unpackedData配列のキーを基にローカル変数を作成します。
34    // 例えば、$unpackedData['short_val'] は $short_val 変数になります。
35    // EXTR_OVERWRITE は、既存の変数を上書きすることを指定します。
36    // 通常、extractの使用は慎重に行うべきですが、この例ではデモンストレーションのために使用します。
37    extract($unpackedData, EXTR_OVERWRITE);
38
39    echo "\n--- extract後の変数アクセス ---\n";
40    // extractによって作成された変数に直接アクセスします。
41    echo "Short Value: " . $short_val . " (型: " . gettype($short_val) . ")\n";
42    echo "Long Value: " . $long_val . " (型: " . gettype($long_val) . ")\n";
43    echo "Message: " . $message . " (型: " . gettype($message) . ")\n";
44
45    // 変数が存在することを確認
46    echo "\n--- 変数の存在確認 ---\n";
47    echo "Is \$short_val set? " . (isset($short_val) ? 'Yes' : 'No') . "\n";
48    echo "Is \$long_val set? " . (isset($long_val) ? 'Yes' : 'No') . "\n";
49    echo "Is \$message set? " . (isset($message) ? 'Yes' : 'No') . "\n";
50}
51
52// 関数の実行
53demonstrateUnpackAndExtract();
54
55?>

このサンプルコードは、PHPのunpack関数とextract関数を組み合わせ、バイナリ文字列からデータを抽出し、それをPHPの扱いやすい個別の変数として利用する方法を示しています。

unpack関数は、バイナリ文字列(コンピュータが直接理解する形式のデータ)を、PHPの連想配列に変換する際に使用します。引数$formatでバイナリデータの形式(例えば、符号付きショート整数はs、文字列はA*)と各データに割り当てるキー名を指定し、$stringで変換したいバイナリ文字列を渡します。$offsetはデータの読み込みを開始する位置です。成功するとデータが格納された配列を返し、失敗するとfalseを返します。サンプルでは、pack関数で作成したバイナリデータから、指定した形式(slA*)に基づいてshort_vallong_valmessageというキーを持つ配列を生成しています。

次にextract関数は、このunpackで得られた連想配列のキーを基に、同じ名前のローカル変数を新しく作成します。例えば、$unpackedData['short_val']という配列要素は$short_valという変数として直接アクセスできるようになります。引数$arrayに展開したい配列を渡し、$flagsで既存の変数との衝突時の挙動などを指定できます(例: EXTR_OVERWRITEは既存の変数を上書きします)。

この一連の処理により、複雑なバイナリデータをPHPのプログラム内で簡単に扱えるようになり、システム開発において様々な場面で活用することができます。

unpack関数のフォーマット文字列は、バイナリデータの構造を正確に指定する必要があり、誤ると意図しない結果を招きます。また、unpack関数の戻り値は失敗時にfalseとなるため、必ずエラーチェックを行うことが重要です。特にextract関数の使用には細心の注意が必要です。この関数は配列のキーを基にローカル変数を作成するため、意図しない変数名の上書きや、外部からの入力を含む配列を扱う場合に変数汚染攻撃などのセキュリティリスクが生じる可能性があります。通常、extractの安易な使用は避け、$unpackedData['key']のように配列として明示的にデータにアクセスする方が、コードの安全性と可読性を高く保てます。EXTR_OVERWRITEなどの第二引数も理解し、慎重に利用してください。

PHP unpack で連想配列を生成する

1<?php
2
3/**
4 * unpack() 関数を使用してバイナリ文字列から連想配列を生成する例。
5 *
6 * この関数は、バイナリデータ(例: ネットワークパケット、ファイルヘッダーなど)を
7 * 読みやすいPHPの連想配列に変換する際に役立ちます。
8 * フォーマット文字列でフィールド名とデータ型を指定することで、
9 * 結果が連想配列として返されます。
10 */
11function demonstrateUnpackAssociativeArray(): void
12{
13    // 例として、2つのバイトからなるバイナリデータを定義します。
14    // \x01 は10進数の1、\x0A は10進数の10に相当します。
15    $binaryData = "\x01\x0A"; // データ例: 'タイプ' = 1, '長さ' = 10
16
17    // unpack() 関数のフォーマット文字列を定義します。
18    // 'Ctype' は最初のバイトを符号なし文字(C)として読み込み、そのキー名を 'type' とします。
19    // 'Clength' は次のバイトを符号なし文字(C)として読み込み、そのキー名を 'length' とします。
20    // スラッシュ '/' は各フィールドの区切り文字として機能します。
21    // この命名規則により、unpack() は結果を連想配列として返します。
22    $format = 'Ctype/Clength';
23
24    // unpack() 関数を呼び出し、バイナリデータを連想配列に変換します。
25    // 第1引数: フォーマット文字列(キー名とデータ型を指定)
26    // 第2引数: 解析対象のバイナリ文字列
27    $unpackedData = unpack($format, $binaryData);
28
29    // unpack() が失敗した場合(例: 不正なフォーマット文字列、データ不足など)は false を返します。
30    if ($unpackedData === false) {
31        echo "エラー: unpack() に失敗しました。" . PHP_EOL;
32    } else {
33        // 成功した場合、結果は連想配列として取得されます。
34        // この例では、['type' => 1, 'length' => 10] となります。
35        print_r($unpackedData);
36    }
37}
38
39// 関数を実行して、unpack() の結果を表示します。
40demonstrateUnpackAssociativeArray();

PHPのunpack関数は、バイナリ形式のデータ(例えばネットワーク通信のパケットやファイルヘッダーなど)を、PHPで扱いやすい連想配列の形に変換する際に使用されます。

この関数は、主に3つの引数を取ります。第1引数$formatは、バイナリデータのどの部分を、どのようなデータ型で、どのようなキー名で読み込むかを指定する「フォーマット文字列」です。この文字列でスラッシュ(/)を用いてキー名を指定することで、結果が連想配列として返されます。サンプルコードの'Ctype/Clength'では、最初のバイトをtype、次のバイトをlengthというキー名でそれぞれ符号なし文字(C)として読み込むことを指示しています。第2引数$stringは解析対象となるバイナリデータそのもので、サンプルコードでは"\x01\x0A"という2バイトのデータが使用されています。第3引数$offsetは省略可能で、指定した場合、バイナリデータのどの位置から読み取りを開始するかをバイト単位で指定できます。

unpack関数は、処理が成功すると、フォーマット文字列で指定されたキー名と変換された値を持つ連想配列を返します。例えば、サンプルコードでは['type' => 1, 'length' => 10]のような結果が得られます。もしフォーマット文字列に誤りがあるなど、処理に失敗した場合はfalseが返されますので、結果がfalseでないかをチェックすることが重要です。この機能は、外部システムとの連携でバイナリデータを扱う際に非常に役立ちます。

unpack()関数は、バイナリ文字列をPHPのデータに変換する際に、フォーマット文字列の指定が非常に重要です。サンプルコードのようにCtypeのようにデータ型指定子に続けてキー名を指定することで、結果が連想配列として得られます。この命名規則を守らないと、数値インデックスの配列になるか、エラーとなります。スラッシュは各フィールドの区切りとして使用します。

また、unpack()関数は、フォーマットが不正だったり、バイナリデータが不足していたりする場合にfalseを返すことがあります。そのため、必ず戻り値がfalseでないかを確認し、適切にエラーハンドリングを行うようにしてください。これにより、プログラムが予期せぬエラーで停止するのを防ぎ、安全にコードを利用できます。より複雑なデータ型指定子については、PHP公式マニュアルで詳細を確認することをお勧めします。

PHP unpack関数でバイナリからデータ抽出

1<?php
2
3/**
4 * PHPのunpack関数を用いて、バイナリ文字列からデータを抽出するサンプル。
5 * システムエンジニアを目指す初心者向けに、基本的な使い方を解説します。
6 *
7 * unpack関数は、バイナリ文字列(バイト列)をPHPの通常のデータ型(整数、文字列など)に変換するために使用されます。
8 * 主に、ネットワークプロトコルの解析、バイナリファイルの読み込み、特定フォーマットのデータ処理などに利用されます。
9 *
10 * @return void
11 */
12function demonstrateUnpackBasic(): void
13{
14    // 1. 非常にシンプルな例: 16ビットの符号なし整数をアンパック
15    // pack関数は、unpackの入力となるバイナリ文字列を生成するために使用します。
16    // 'S' は16ビット符号なし整数 (unsigned short) を意味し、マシンバイトオーダーに従います。
17    $packedUint16 = pack('S', 42); // 数値 42 をバイナリ形式に変換
18    echo "元の数値: 42\n";
19    echo "パックされたバイナリ (16ビット符号なし): " . bin2hex($packedUint16) . "\n";
20
21    // 'Svalue' とすることで、結果の配列のキーを 'value' に指定できます。
22    $unpackedUint16 = unpack('Svalue', $packedUint16);
23
24    if ($unpackedUint16 === false) {
25        echo "エラー: unpackに失敗しました。\n";
26        return;
27    }
28
29    echo "アンパックされた値 (キー 'value'): " . $unpackedUint16['value'] . "\n\n";
30
31    // 2. 複数の異なるデータ型をアンパックする例
32    // 'C': 8ビット符号なし文字 (unsigned char)
33    // 'a5': 5バイトのヌル埋め文字列
34    // 'i': マシンバイトオーダーの符号付き整数 (signed integer)
35    $multiPackedData = pack('Ca5i', 255, 'Hello', -12345);
36    echo "複数のデータ型をパックしたバイナリ: " . bin2hex($multiPackedData) . "\n";
37
38    // フォーマット文字列をスラッシュ '/' で区切ることで、複数の値をアンパックできます。
39    // 各フォーマットに名前を付けることで、結果の配列のキーを分かりやすくします。
40    $unpackedMultiData = unpack('Cbyte/a5text/iint', $multiPackedData);
41
42    if ($unpackedMultiData === false) {
43        echo "エラー: 複数のデータ型unpackに失敗しました。\n";
44        return;
45    }
46
47    echo "アンパックされた複数の値:\n";
48    echo "  byte (C): " . $unpackedMultiData['byte'] . "\n";     // 期待値: 255
49    echo "  text (a5): " . $unpackedMultiData['text'] . "\n";    // 期待値: "Hello"
50    echo "  int (i): " . $unpackedMultiData['int'] . "\n\n";     // 期待値: -12345
51
52    // 3. オフセットを指定してアンパックする例
53    // 最初の数バイトをスキップして、それ以降のデータを読み込みます。
54    // ここでは、文字列 "HEAD" (4バイト) の後に 12345 のバイナリ表現をパックします。
55    $dataWithHeader = pack('a4S', 'HEAD', 12345);
56    echo "ヘッダー付きパックデータ (バイナリ): " . bin2hex($dataWithHeader) . "\n";
57
58    // unpackの第3引数でオフセットを '4' に指定し、4バイト (HEAD部分) をスキップして、
59    // その後の16ビット符号なし整数をアンパックします。
60    $unpackedWithOffset = unpack('Sdata', $dataWithHeader, 4);
61
62    if ($unpackedWithOffset === false) {
63        echo "エラー: オフセット付きunpackに失敗しました。\n";
64        return;
65    }
66
67    echo "オフセット指定でアンパックされたデータ (4バイトスキップ): " . $unpackedWithOffset['data'] . "\n"; // 期待値: 12345
68}
69
70// 関数を実行して、サンプルコードの動作を確認します。
71demonstrateUnpackBasic();

PHPのunpack関数は、バイナリ文字列(バイト列)をPHPの通常のデータ型(整数、文字列など)に変換するために使用される拡張機能です。主に、ネットワークプロトコルの解析やバイナリファイルの読み込み、特定フォーマットのデータ処理などに活用されます。

この関数は、第一引数 $format に変換したいデータ型やバイト数を示すフォーマット文字を、第二引数 $string に変換対象のバイナリ文字列を指定します。例えば、'S'は16ビット符号なし整数、'a5'は5バイトのヌル埋め文字列を意味します。複数のデータを変換する際は、フォーマット文字をスラッシュで区切り、結果の配列のキー名を指定することも可能です。オプションの第三引数 $offset を指定すると、バイナリ文字列の先頭から指定バイト数だけスキップした位置から変換を開始できます。

処理が成功した場合、unpack関数は抽出されたデータをキーと値のペアで格納した連想配列を返します。何らかの理由で変換に失敗した場合は、falseが返されるため、戻り値をチェックしてエラーハンドリングを行うことが重要です。

サンプルコードでは、まず数値42を16ビット符号なし整数としてバイナリにパックし、それをunpackで元の数値に戻す基本的な使い方を示しています。次に、8ビット符号なし整数、5バイト文字列、符号付き整数といった複数の異なるデータ型を一度にアンパックする方法を解説し、最後にオフセットを指定してバイナリ文字列の途中からデータを抽出する例を紹介することで、unpack関数の実用的な利用方法を具体的に理解することができます。

unpack関数を利用する際は、第一引数のフォーマット文字列は特に重要です。バイナリデータの構造に合わせて正確なフォーマットコード(バイト数、符号の有無、特にバイトオーダー)を指定しないと、意図しないデータ解釈やエラーの原因となります。unpackは処理に失敗するとfalseを返しますので、結果を必ず厳密な比較(=== false)で確認し、エラーハンドリングを行ってください。バイナリデータはファイルやネットワーク通信など外部から来るケースが多いため、データの仕様を事前に正確に把握することが重要ですし、pack関数と組み合わせて挙動を理解すると良いでしょう。第3引数のオフセットを使う際は、スキップするバイト数を正確に指定してください。

PHP unpack関数でバイナリ展開する

1<?php
2
3/**
4 * バイナリデータから特定の形式で値を展開(アンパック)するサンプル。
5 *
6 * `unpack`関数は、バイナリ文字列をPHPの配列として解析し、指定されたフォーマットに基づいて値を抽出します。
7 * これは、ネットワークプロトコルのパケット解析やバイナリファイルの読み込みなどで、
8 * バイナリデータを構造化されたデータとして扱う際に役立ちます。
9 */
10function demonstrateUnpack(): void
11{
12    // 例1: 簡単なバイナリデータの展開
13    // 'C' は符号なし8ビット整数 (1バイト) を意味します。
14    // '*' を使うと、残りのデータをすべて同じフォーマットで展開し、1から始まる連番のキーで格納します。
15    $binaryString1 = "\x01\x02\x03"; // 1, 2, 3 というバイト列を表すバイナリ文字列
16    echo "--- 例1: 符号なし8ビット整数として展開 (キー名なし) ---\n";
17    $result1 = unpack('C*', $binaryString1);
18    if ($result1 !== false) {
19        print_r($result1);
20    } else {
21        echo "アンパックに失敗しました。\n";
22    }
23
24    echo "\n";
25
26    // 例2: 異なるフォーマットとキー名を使った展開
27    // フォーマット文字列はスラッシュ ('/') で区切ることで複数の形式を指定できます。
28    // 'Cfirst_byte': 最初の1バイトを符号なし8ビット整数として 'first_byte' キーに格納。
29    // 'nshort_int': 次の2バイトをビッグエンディアン (上位バイトが先) の符号なし16ビット整数として 'short_int' キーに格納。
30    // 'aString': 残りのバイトを文字列として 'String' キーに格納。
31    // pack関数を使って、対応するバイナリデータを作成します。
32    $packedData = pack('CnA4', 10, 258, 'TEST'); // 10 (1バイト), 258 (2バイト: 0x0102), 'TEST' (4バイト)
33    // 生成されるバイナリデータ例: \x0A\x01\x02TEST
34    echo "--- 例2: 複数の異なるフォーマットとキー名で展開 ---\n";
35    echo "パックされたデータ (バイナリ表現): " . bin2hex($packedData) . "\n";
36    $format2 = 'Cfirst_byte/nshort_int/aString';
37    $result2 = unpack($format2, $packedData);
38    if ($result2 !== false) {
39        print_r($result2);
40    } else {
41        echo "アンパックに失敗しました。\n";
42    }
43
44    echo "\n";
45
46    // 例3: オフセットを指定してデータの途中から展開
47    // 例2で使ったデータを再利用し、データの途中から読み込みを開始します。
48    // オフセット1を指定すると、最初の1バイトをスキップし、2バイト目から展開を開始します。
49    echo "--- 例3: オフセットを指定して展開 ---\n";
50    // オフセット1バイトから開始すると、パックされたデータの \x01\x02TEST の部分が処理されます。
51    $format3 = 'nshort_int/aString';
52    $result3 = unpack($format3, $packedData, 1); // 1バイト目(オフセット1)から展開を開始
53    if ($result3 !== false) {
54        print_r($result3);
55    } else {
56        echo "アンパックに失敗しました。\n";
57    }
58}
59
60// 関数を実行して、アンパックの動作を確認します。
61demonstrateUnpack();

PHP 8のunpack関数は、バイナリ文字列をPHPの配列に変換し、指定されたフォーマットに基づいてその内容を展開する(アンパックする)ために使用されます。ネットワーク通信のパケット解析やバイナリファイルの読み込みなど、構造化されたバイナリデータを扱う際に非常に役立つ機能です。

この関数は、第1引数$formatに、バイナリデータの形式とPHP配列のキー名を定義するフォーマット文字列を受け取ります。例えば、'C'は1バイトの符号なし整数、'n'はビッグエンディアンの2バイト符号なし整数、'a'は文字列などを示し、複数のフォーマットをスラッシュで区切って指定できます。第2引数$stringには、展開したい元のバイナリデータ文字列を渡します。オプションの第3引数$offsetを指定すると、バイナリ文字列の特定のバイト位置から展開を開始することが可能です。

処理が成功すると、unpack関数はフォーマット文字列で指定されたキー名と、展開された値のペアを含む連想配列を返します。展開に失敗した場合はfalseが返されるため、戻り値を確認することが重要です。

サンプルコードでは、まずシンプルなバイト列を符号なし8ビット整数として展開する基本例を紹介しています。次に、pack関数で作成した複数の異なる形式のバイナリデータ(数値と文字列)を、それぞれキー名を付けてPHP配列として展開する方法を示しています。さらに、$offset引数を利用して、バイナリデータの途中から展開を開始し、特定のデータ部分のみを抽出する応用例も確認できます。これにより、複雑なバイナリデータから必要な情報を効率的に取得することが可能になります。

PHPのunpack関数は、バイナリデータを特定のフォーマットでPHPの配列に変換する際に利用します。フォーマット文字列はバイトオーダーやデータの種類、長さを厳密に指定する必要があり、誤ると意図しない結果になりますので注意が必要です。関数が失敗した場合にはfalseを返すため、必ず戻り値をチェックし、適切にエラー処理を行ってください。また、offset引数はデータの読み込み開始位置をバイト単位で指定するもので、データの途中から解析する際に便利です。通常、バイナリデータを作成するpack関数と組み合わせて使われます。なお、PHPのunpack関数は、配列や引数を展開する「アンパック演算子(...)」とは全く異なる機能ですので、混同しないようにしてください。

関連コンテンツ

関連IT用語

関連プログラミング言語