今日のCPANモジュール

2008-06-11 16:35  

use Encode; (ADVANCED)

ここは本編への補足や本編で取り上げなかった話題について置いておく場所です。

« 本編へ戻る


だいたい同じと乱暴にまとめた latin-1 の話

latin-1 とは俗称で、正式には ISO-8859-1 とか言う。おおざっぱに言うと ascii 127 文字の続きに1バイトに収まる範囲でアクセント記号付きアルファベットとかを付け加えたもの()。付け加えるもののバリエーションで latin-2(ISO-8859-2)とかあったりする。

Perl は utf8 フラグのなかった時代のコードもそのまま動くよう、latin-1 の範囲(1バイト = 10進で255以下、16進で xFF 以下)を優遇しその範囲は Encode::decode() なしにフラグが立たないようにしている。(例えば "x{UUUU}"chr 0xUUUU 表記)

なので Data::Dumper で "x{UUUU}" 表記になるか見るだけで utf8 フラグが立っているかどうかを判断するのは実は正確ではない。日本語(非1バイト)を扱っている場合はだいたいそれでわかりますが。

この辺は主に入出力を担当するモジュールを書く人が気をつけるべき話題で、モジュールを作る人はできるだけ利用者が Unicode だけを使えばよいようにしてあげよう。ということで本編では流した。モジュールでの Unicode 利用の歴史: 1, 2, 3

自身でフラグを気にしなければいけない場合は Data::Visitor::Encode が便利。

まったく登場しない utf8:: の話

utf8::decode()Encode::decode() と違い latin-1 の範囲はフラグを立てないのでその差に注意しなければならない。あと日本人はどうせ utf8::* だけでは済まないことが多い。なので utf8:: ではなく Encode::* 推奨とした。

同様の理由で Catalyst でエンコーディングが UTF-8 だけの場合は使えるのだけど C::P::Unicode は割愛した。

まったく登場しない encoding プラグマの話

非推奨であるのとソースは UTF-8 を使えるケースが多いと思うのでスルー。

まったく登場しない PerlIO の話

Perl には PerlIO というファイルハンドル動作のラッパー機能があり、これを使ってファイル open や print の時 自動で decode()/encode() させることができる。

PerlIO は便利だけどこれ専用の機能ではないし Encode::decode()/ Encode::encode() で済むといえば済むので、よくわからないうちは無理に使わなくても良いと思いスキップ。あくまでも便利機能という位置づけとした。

ここで簡単に触れておきます。PerlIO の使い方は3パターン。それぞれ例を示します。

と、decode()/encode() を書かずに透過的に decode()/encode() できます。PerlIO レイヤは :utf8:encoding() タグ以外にもいろいろあったりします。入出力のラッパーだと認識した上で使うと便利です。

cp932 の話

Encode の Shift_JIS エンコーディングは純粋な Shift_JIS。Microsoft が Shift_JIS を拡張して入れた ①㈱ みたいな文字を含む Shift_JIScp932 というエンコーディングで別に入っている。機種依存文字も最近は Mac でも見れたり入力できたりするので、cp932 をつかっておけばよい、とした。

この話題についてはLegacy Encoding Project に詳しい。shift_jis に対する cp932 と同じようなポジションで Encode::EUCJPMS や Encode::ISO2022JPMS(開発中?)がある。

波ダッシュ/全角チルダ問題

charset=Shift_JIS な HTML からキーボードから普通に入力した「~」は、shift_jisdecode() すると U+301C に、cp932 では U+FF5E にマッピングされる。さらに、charset=UTF=8 な HTML からは Windows と Mac で違うのが来て、utf-8decode() すると Windows からのは U+FF5E に、Mac からのは U+301C にマッピングされる。

問題は encode() 時で、shift_jis には U+FF5E に対応するのがない。まあ shift_jis には機種依存文字もないので良いが、cp932 は機種依存はあるが U+301C に対応するのがないので ? になる。

といっても実際問題になるケースは少なく、Mac から decode('utf-8') したのを encode('utf-8') して保存しておいて、場合によっては decode('cp932') で出すというケースとかだが、Encode::FB_HTMLCREF を使うのは嫌でどうしても出したい時は

# cp932 を使って encode() する場合。shift_jis でやる場合は逆にする
$text =~ s/x{301C}/x{FF5E}/g; # WAVE DASH to FULLWIDTH TILDE
print encode('cp932', $text);

みたいに置換してから encode() という方法がある。

しかしこれって「PC/携帯 でデータを共有するサービス」が想定されるケースであり、携帯に特化したエンコーディングパックを追加する Encode::JP::Mobileshift_jis 系エンコーディング(x-sjis-docomo)とかは cp932 ベースだが U+301C も特別に入っているので置換とかする必要がないので普通にこれを使えば良い。(今のところ波ダッシュ以外の違う奴はサポートしていないが)

その他、Unicode / Encode に関係あるけど割愛したもの

正規表現

Encode


本編へ戻る

WRITTEN BY

冨田 尚樹 <tomita@cpan.org>