2009-12-29

PerlのEncodeモジュールは何を何にエンコードするのか

概要

Perlの文字コード変換用のモジュールEncode.pmの入門用記事は色々ありますが、入門の入門が必要なくらい説明が足りていないと思うので、記事にしてみます。

タイトルの問題の答え

タイトルにした問題の答えは、「夢の国のPerl内部表現文字列を、現実の世界の文字列(バイト列)にエンコードする(変換する)」です。

具体的には、関数$bytes = encode($charset, $string)はPerl内部表現文字列から外に出ていくバイト列を生成する(エンコードする)のに使って、$string = decode($charset, $bytes)は外からバイト列をPerl内部表現にデコードするという感じです。

ご存知かとは思いますが、モジュールの名前はEncodeなのに、なんと逆変換のdecodeもできます。

混乱を誘うさまざまな機能

そして混乱することに、utf8encodingがあります。これらのモジュールはすべて小文字なので、Perlインタプリタの動作を変更するプラグマモジュールであり、ソースコードのエンコーディングを指定するという意味です。

このプラグマを有効にすると、文字列リテラルが単なるバイト列ではなく、Perl内部表現にdecodeされた状態で構文木が作られます。そんな必要がないなら指定してはいけません。

またさらに混乱することに、PerlIOの拡張によって、標準入出力、エラー出力、ファイル入出力で指定可能になる、フィルタの機能を使うと、透過的にエンコード、デコードが起こって何が起こっているのか良く分からなくなるので、encode, decodeを自在に操れるようになってから触るとよいです。

デバッグ方法

Devel::PeekでPerl内部表現文字列かどうかを表すutf8フラグを含めてDumpして観察する。\012みたいなのは1バイトを8進数3桁で表したもの。