PerlのEncodeについて
とある事情でCGIをひさびさに書くことになった。
置くのがレンタルサーバということもあり、言語はPerlを選んだ。
ここで文字コードを変換する必要があり、その際にEncodeの使い方を日本語のWebPageの範囲で調べてみたがピンとこない。
そこで、CPANの小飼氏の文章を読むと、ストンと腑に落ちた。
http://search.cpan.org/dist/Encode/Encode.pm
乱暴にではあるが、まとめることでメモ(備忘録)とする。
Perlにとっては原則データは単なるバイトの並びとして扱ってきた。これは文字列とて同様である。(もともとPerlはアメリカ人によって開発されたため、ASCIIが扱えればそれで充分だったのだ。)
しかし、このままではマルチバイト文字列を扱えないため、5.6以降のPerlでは以下の策をとることにした。
文字列中に1バイトよりも大きな文字コードを含む文字を文字列中に含むとき、必ずUTF8で文字コード格納する。
ただ、これだとバイト列と見分けがつかないため、'UTF8フラグ'をONにすることでバイトストリームと文字列を区別して扱えるようにする。
つまり、Perlにとって「UTF8の文字コードが連続したデータ列でかつUTF8フラグがONになっている」のがPerlの内部文字列データと呼ぶことができる。
Encode()は「他の文字列コードにデータを変換する」という捉え方でなく、「Perlの内部文字列データから、単なるバイトストリームへの変換」という視点で捉える必要がある。
$octets = encode("shiftjis", $string);
というのは、Perlの内部文字列から「文字コードをUTF-8からシフトJISに変換しUTF8フラグをOFFした値」に変換することである。
いくらシフトJISの文字コードが連続していて、文字として意味があっても、変換後の値$octetsは単なるバイト列にすぎない。
decodeはその逆で「あるバイト列を第一引数で指定した文字コードで構成されていると見なし、その値をUTF-8の文字コードでかつUTF8フラグをONにした内部文字列データ」に変換する。
では、from_to()は?
from_to()とは文字コードを変換するだけのI/Fであり、UTF8フラグを操作しない。
したがって、たとえUTF8に変換しても、そのままではPerlにとって単なるバイト列にすぎない。
この点注意が必要である。