バイナリーデータに変換する
pack は、TEMPLATE に与えられたルールに基づいて、LIST
のそれぞれの値をバイナリーデータに変換し、変換したすべての値を結合したバイナリーデータを返します。
何かしらのバイナリーデータを扱う場合には、このバイナリーデータを生成する pack と、
バイナリーデータから意味を読み取る unpack
は欠かすことができない関数です。
とりわけ、バイナリーファイルを扱う場合や、
ネットワーク上のパケット生成や解析においては避けては通れない関数です。
次のサンプルは IP アドレス "192.168.11.3" を 4 バイトのバイナリーデータに変換します。
バイナリーデータのままでは中身を確かめられないため、unpack
を使って 16 進数表記の文字列として出力します。
my $bin = pack( 'C4', split(/\./, '192.168.11.3') );
print unpack('H*', $bin); # c0a80b03
このサンプルコードの pack に与えられた TEMPLATE は C4 ですが、
C は符号なし 8 ビット整数 (unsigned char) を意味しており、
その後の 4 は 4 つという意味です。
つまり「1 バイトの 0 ~ 255 の値が 4 つ」という意味になります。
C4 は CCCC と記述することもできます。
split(/\./, '192.168.11.3') は pack の引数の
LIST に相当し、"192", "168", "11", "3"
という 4 つの数字を表す文字列になります。
最終的には、"192" や "168" などの数字を表す文字列をそれぞれ 1 バイトの数値とみなしてバイナリーデータに変換し、それら 4 つを結合する、ということになります。
TEMPLATE には数多くの文字が定義されていますが、ここでは良く使われるテンプレート文字に限定して紹介します。
すべての仕様を確認したい場合は、
公式の Perldoc の説明をご覧ください。
| 文字 | 説明 |
|---|---|
| a | null 埋めの文字列
utf8 フラグが ON の内部文字列を扱う場合は、
外部文字列にした時点でバイナリーデータになります。
|
| A | スペース埋めの文字列
テンプレート |
| Z | null 終端かつ null 埋めの文字列
テンプレート |
| b | ビット列 (各バイト内では昇ビット順で vec() と同様)
テンプレート |
| B | ビット列 (各バイト内では降ビット順)
テンプレート |
| h | 16 進数文字列 (低位ニブルが先)
テンプレート |
| H | 16 進数文字列 (高位ニブルが先)
テンプレート |
| c | 符号付き 8 ビット整数 (signed char)
テンプレート |
| C | 符号なし 8 ビット整数 (unsigned char)
テンプレート |
| s | 符号付き 16 ビット整数 (signed short)
テンプレート |
| S | 符号なし 16 ビット整数 (unsigned short)
テンプレート |
| l | 符号付き 32 ビット整数 (signed long)
テンプレート |
| L | 符号なし 32 ビット整数 (unsigned long)
テンプレート |
| q | 符号付き 64 ビット整数 (signed quad)
テンプレート なお、テンプレート |
| Q | 符号なし 64 ビット整数 (unsigned quad)
テンプレート なお、テンプレート |
| n | 符号なし 16 ビット整数 (unsigned short) でビッグエンディアン
テンプレート |
| N | 符号なし 32 ビット整数 (unsigned long) でビッグエンディアン
テンプレート |
| v | 符号なし 16 ビット整数 (unsigned short) でリトルエンディアン
テンプレート |
| V | 符号なし 32 ビット整数 (unsigned long) でリトルエンディアン
テンプレート |
| f | 単精度浮動小数点数
テンプレート |
| d | 倍精度浮動小数点数
テンプレート |
以上、良く使うテンプレート文字を解説しましたが、pack には他にも細かい機能が用意されています。
ウェブアプリケーション開発であればそこまで細かい機能を使うこともないでしょうが、もし興味があれば、
Perl 公式サイトのドキュメントをご覧ください。