PHPのunpack関数を活用する | katyos開発室

katyos開発室

Webサービス作ったりブログ書いたりしてます。

てきとー てきとー

PHPでバイナリデータを扱いたい場合、pack/unpack関数を使うと便利です。

しかし、マニュアルにはあまり詳しい使い方が書かれていないので、unpack関数、特に書式コードをどう使えばいいか解りにくいのが難点です。ネットで検索してもあまり纏まった記事も見つかりませんでした。

そこで、PHPのunpack関数を利用してバイナリファイルを読み込む際に調べた事をまとめてみました。


基本的に以下の4つを繰り返します。

1.フォーマットコード
 PHPマニュアル参照

2.繰り返し回数(1回のみなら省略可能)
 0:   スキップされる
 1~: 指定回数繰り返す
 *:   データの末尾まで繰り返す

3.配列のキー(省略可能)
・数字で始まるキーは使用できない(直前の繰り返し数と区別ができないため?)。
ただし、繰り返し数が*の場合は数字を利用可能。

 例1: unsigned char型、繰り返し数2回、インデックス文字列は「00」で始まる値
  unpack("C200",$data);  // ×:指定できない。 200回繰り返しと判別される

 例2: unsigned char型、最後まで繰り返し、インデックス文字列は「00」で始まる値
    unpack("C*00",$data); // ○:指定できる。

・繰り返しを指定した場合、1から始まる連番が追加される(0からではないので注意)

  $arr = unpack("C*",$data);
    ↓
  $arr[1]、$arr[2]、$arr[3]・・・


・配列のキーを指定した場合は、末尾に1から始まる連番が追加される。

  $arr = unpack("C5data",$data);
    ↓
  $arr[data1]、$arr[data2]、$arr[data3]・・・


4.区切り(書式を繋げないなら省略可能)
”/”をデリミタとして指定すれば、複数のフォーマット書式をつなげる事ができる。

  $arr = unpack("itype/S3head/C*data",$data);
    ↓
  $arr[type]   // signed int
  $arr[head1]  // unsigned shrot
  $arr[head2]  // unsigned shrot
  $arr[head3]  // unsigned shrot
  $arr[data1]   // unsigned char
  $arr[data2]   // unsigned char
     ・
     ・
     ・

以上です。

書式を上手く組み合わせれば、画像データなど固定長フォーマットのデータをPHPで読み込む際に便利です。


最後にサンプルとして、PNG画像の先頭部分を配列を読み込む書式を紹介します。

■unpack関数を使ってPNGファイルのヘッダー部分を読み込むサンプル


$filename = "test.png";
$fh = fopen($filename, 'rb');
$bindata = fread($fh, filesize($filename));
fclose($fh);

$arr = unpack("C8sig/IIHDR_Length/IIHDR_ChunkType/IIHDR_width/IIHDR_height/CIHDR_BitDepth/CIHDR_ColorType/CIHDR_Compress/CIHDR_Filter/CIHDR_Interlace/IIHDR_CRC", $bindata);

print_r($arr);



※上記コードの実行結果


Array
(
[sig1] => 137
[sig2] => 80
[sig3] => 78
[sig4] => 71
[sig5] => 13
[sig6] => 10
[sig7] => 26
[sig8] => 10
[IHDR_Length] => 218103808
[IHDR_ChunkType] => 1380206665
[IHDR_width] => 838860800
[IHDR_height] => 838860800
[IHDR_BitDepth] => 4
[IHDR_ColorType] => 3
[IHDR_Compress] => 0
[IHDR_Filter] => 0
[IHDR_Interlace] => 1
[IHDR_CRC] => 346363547
)