packとunpack

perlやphpにあるpack,unpack関数はシリアライズとデシリアライズを行う関数です。シリアライズとは数値や文字列をバイナリ表現にすることで、デシリアライズはその逆です。シリアライズしたデータはネットワークに送ったり、保存したりしやすくなります。しかしシリアライズには常にいろいろな問題が付きまといます。

文字列をpackする。

文字列をpackするには常に長さを固定して行います。以下の例は長さ10バイトでpackします。

$str = "abcd";
$b = pack("a10", $str);

“a10″のaは文字列を表し、10は長さを指定します。$strが10バイトより短ければ、残りの部分はnullでうめられます。”a10″の代わりに”A10″とすればスペースで埋められます。

文字列をunpackする。

$str = "abcd";
$b = pack("a10", $str);
$str2 = unpack("a10", $b);

上の例のように、packやunpackの最初の引数はどのようにシリアライズやデシリアライズするのかを指定します。しやしややこしいのは、この引数はpackとunpackで対照的でなく、しかもperlとPHPで挙動が違うことです。その上PHPにはまともなマニュアルがないのでここではperlを中心に考えます。上記の例だと$str2にはnullが6ついていて、$strと同じではありません。

そこでこの第一引数である型指定について、文字列に関してまとめると次のようになります。

packの”a10″ : 10バイトとってくる。残りはnullで埋める
packの”A10″ : 10バイトとってくる。残りはスペースで埋める
packの”Z10″ : “a10″と同じ
unpackの”a10″ : 10バイトそのままとってくる。
unpackの”A10″ : 10バイトとってきてnullやスペースで埋まってるものを取り除く
unpackの”Z10″ : 10バイトとってきて最初のnull以降を取り除く

よって以下のようにすればいいはず。
$str = "abcd";
$b = pack("a10", $str);
$str2 = unpack("A10", $b);

しかしこれだと、以下のようにうまくいかなくなる場合もある。
$str = "abcd ";
$b = pack("a10", $str);
$str2 = unpack("A10", $b);

まとめ

aやAやZはあんまり使わない方がいい?

つづく

Leave a Reply

Your email address will not be published. Required fields are marked *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)