pack関数 - データをバイナリ形式にパックする
pack関数は、データをさまざまなバイナリ形式にパックします。
my $packed = pack($format, @values);
第一引数はバイナリ形式のデータフォーマットを指定します。
第二引数以降は、値のリストを指定します。
戻り値は、パックされたデータです。
符号付32bitのバイナリ形式にパック
一つの例として、三つの整数を符号付32bitのバイナリ形式にパックするには次のようにします。
my $packed = pack("l3", 7, 8, 9);
まず、7, 8, 9というのは、Perlのデータです。これを符号付32bitのバイナリ形式にパックします。
「l」という記号が「符号付32bit整数」ということを表現しています。
その後に続く3というのが「3つの値」ということを表現しています。
フォーマットは「バイナリ形式を表す記号」と「長さ」によって構成されています。
全体では、7, 8, 9という数値を、符号付32bit整数が3つ続くバイナリ形式でパックするという意味になります。
今回の例では引数にリストを渡していますが配列を渡すこともできます。
my @values = (7, 8, 9); my $packed = pack("l3", @values);
浮動小数点を符号付doubleのバイナリ形式にパック
三つの浮動小数点を倍精度浮動小数点doubleのバイナリ形式にパックしてみましょう。
my $packed = pack("d3", 0.5, 1.2, 5.4);
倍精度浮動小数点は「d」という記号でパックすることができます。
バイナリデータを書き込むには
バイナリデータを書き込むにはファイルハンドルをbinmode関数を使ってバイナリモードにして、print関数を使用します。
# パックされたバイナリデータ my $packed = pack("l3", 7, 8, 9); # ファイルをオープン open my $fh, '<', $file or die "Can't open $file:$!"; # バイナリモードに変更 binmode $fh; # バイナリデータを書き込み print $fh $data; # ファイルをクローズ close $fh;
エンディアンを変更するには
ビッグエンディアンからリトルエンディアンの変換は「N」と「V」を使って行うことができます。以下の例は符号なし32bit整数の例です。
# ビッグエンディアンの値をPerlの値に my $value = unpack('N1', $value_big); # Perlの値をリトルエンディアンに my $value_litte = pack('V1', $value);
パックされたデータを元に戻すには
パックされたデータを復元するにはunpack関数を使用します。
フォーマットの一覧
pack関数のフォーマットの一覧。
a | 任意のバイナリデータを含む文字列。ヌルパディングされます。 |
A | テキスト(ASCII)文字列。スペースで埋められます。 |
Z | ヌルで終了する(ASCIZ)文字列。ヌルで埋められます。 |
b | ビットストリング(vec関数のような各バイト内で昇順のビット順序) |
B | ビットストリング(各バイト内の降順ビット順序) |
h | 16進文字列(低いニブルが最初) |
H | 16進文字列(高いニブルが最初) |
c | 符号付きchar(8ビット)値 |
C | 符号なしchar(オクテット)値 |
W | 符号なしのchar値(255を超える可能性があります) |
s | 符号付きshort(16ビット)値 |
S | 符号なしのshort値 |
l | 符号付きlong(32ビット)値 |
L | 符号なしのlong値 |
q | 符号付きクォード(64ビット)値 |
Q | 符号なし4倍の値 |
i | 符号付き整数値(少なくとも32ビット。C言語のint) |
I | 符号なし整数値 |
n | ネットワーク(ビッグエンディアン)順の符号なしshort(16ビット) |
N | ネットワーク(ビッグエンディアン)順序で符号なしlong(32ビット) |
v | 「VAX」(リトル・エンディアン)順序の符号なしshort(16ビット) |
V | VAX(リトルエンディアン)順序で符号なしlong(32ビット) |
j | Perlの内部符号付き整数値(IV) |
J | A Perlの内部符号なし整数値(UV) |
f | ネイティブ形式の単精度浮動小数点数 |
d | ネイティブフォーマットの倍精度浮動小数点数 |
F | ネイティブ形式のPerl内部浮動小数点値(NV) |
D | ネイティブフォーマットのlong-double精度のfloat型 |
p | ヌル終了文字列へのポインタ |
P | 構造体へのポインタ(固定長文字列) |
バイナリ形式の利点
バイナリ形式の利点は、サイズが小さくなるということです。Perlの数値は、内部的にはSVという構造体で表現されており、サイズは、構造体のフィールドが存在する分だけ大きいです。
もう一つの利点は、連続した領域に配置されるということです。32bitというのは、4バイトのことですから、4バイトが3つ連続して、12バイトで、整数3つを表現できます。
C言語とのデータのやり取り
C言語の配列はちょうどパックされたバイナリ形式と対応しています。以下の宣言は、パックされたバイナリ形式とちょうど同じデータ構造を持っています。
int32_t values[3];