デコードする
ある文字列が何文字あるのかを求めるプログラムを書くとします。
perlにはlengthという関数があるので、これを使って以下の様なプログラムを書きました。
# UTF-8で保存したファイル use strict; use warnings; my $str = 'ハローワールド'; my $length = length $str; print $length . "¥n"; # 21が出力される
「ハローワールド」は7文字なので、「7」という数字が出力されれば嬉しいですね。
でも実際には「21」と出力されてしまいます。
これは「21バイト」を意味します。
「ハローワールド」は、1文字3バイトで表せられるので、「3 x 7 = 21」です。
つまり、perlには、「ハローワールド」は文字列としてではなく、単なるバイト列として認識されてしまっているのです。
perlに「ハローワールド」を文字列として扱ってもらうためには「デコード」を行う必要があります。
「デコード」は、以下のようにEncodeモジュールを使って行います。
# UTF-8で保存したファイル use strict; use warnings; use Encode; my $str = 'ハローワールド'; # デコード my $decoded_str = Encode::decode('utf-8', $str); my $length = length $decoded_str; print $length . "¥n"; # 7が出力される
デコードされた文字列は、perlに文字列としてちゃんと扱われるようになります。
デコードされた文字列をlength関数に渡すと、きちんと文字数が返ってくるようになります。
ここでデコードされた文字列を「内部文字列」と呼びます。
perlが処理するための独自の文字コードのようなものです。
上記の例では、「UTF-8の文字列をデコードして、内部文字列に変換した」と言えます。
例えば、「Shift_JISの文字列をデコードして、内部文字列に変換」するなら、
以下の様なプログラムを書きます。
my $decoded_str = Encode::decode('Shift_JIS', $str);
このように、まずは文字列をデコードして内部文字列に変換する必要があります。
そうでないと、length関数の例のように、期待した結果が出なくなってしまいます。
エンコードする
以下のようなプログラムを書くと警告が出ます。
use strict; use warnings; use Encode; my $str = 'ハローワールド'; my $decoded_str = Encode::decode('utf-8', $str); print $decoded_str . "¥n";
Wide character in print at test.pl line 9.
これは、内部文字列のまま標準出力をしてしまったからです。
内部文字列はperl独自のものなので、標準出力やファイル書き込みやDBに格納するなど、外に出すときには内部文字列を「エンコード」する必要があります。
「エンコード」は、以下のようにEncodeモジュールを使って行います。
use strict; use warnings; use Encode; my $str = 'ハローワールド'; my $decoded_str = Encode::decode('utf-8', $str); # エンコード my $encoded_str = Encode::encode('utf-8', $decoded_str); print $encoded_str . "¥n";
これで通常にutf8の文字列が出力されるようになりました。
また、Shift_JISの文字列で出力したい場合は、以下のようにエンコードします。
my $encoded_str = Encode::encode('Shift_JIS', $str);
このように、外に出力する場合は、何かの文字コードにエンコードするようにします。