文字コードのあれこれ
あれこれって言っても入力と出力の所について。
文字コード変換はこちら
「Perlの俺ルール - 足跡」で入力と出力の部分についての俺ルールを書きましたが、やはり独りよがりな俺ルールでした。
UTF8文字列での正しい入出力処理はこちら:
404 Blog Not Found:#perl - utf8::decode()ではなくEncode::decode_utf8()を使うべき理由
つまり「外部から入力されたUTF8文字列に対してはEncode::decode_utf8()を使うべし」ということ。
理由としては上記リンク先にも書かれていますが、不正なUTF8文字を無害な文字へと変換する機能が「utf8::decode()」には無いのに対し「Encode::decode_utf8()」には備わっている事が挙げられます。
これによってより簡単な記述でセキュアなスクリプトになります。
要は外部入力を内部表現に変換するのにはEncode使えということだそうです。
使い方例:
use strict; use warnings; use utf8; use Encode; &main(); sub getdata{ # 外部からデータを取得するルーチン。戻り値は文字列。 } sub main{ my $data = getdata(); my $text = Encode::decode_utf8($data); # $textに対する何かの処理。 utf8::encode($text); print $text; }
ただし上記コードが期待通りに動作するのはEncodeモジュールのバージョンが2.13以上での話だそうで。
Encodeのバージョンが2.12以下の環境で上記コードを実行すると、$dataに既にutf8フラグが立っている時にエラーを起こします。
なのでEncodeのバージョンに依らないようにするには以下のような感じ。
use strict; use warnings; use utf8; use Encode; &main(); sub getdata{ # 外部から文字列データ取得 } sub main{ my $data = getdata(); my $text = Encode::is_utf8($data) ? $data : Encode::decode_utf8($data); # $textに対する処理。 utf8::encode($text); print $text; }
入力に使われる文字列のエンコーディングがutf8以外の場合は、Encode::decode()を使うと良い。
その場合は下記のような感じ。
use strict; use warnings; use utf8; use Encode; &main(); sub getdata{ # 外部から文字列データ取得 } sub main{ my $data = getdata(); my $encoding = 'euc-jp'; my $text = Encode::is_utf8($data) ? $data : Encode::decode($encoding, $data); # $text に対する処理 utf8::encode($text); print $text; }
Encode::decode使ってるのが一番平和な気がしないでもない。