メメメモモ

プログラミング、筋トレ、ゲーム、etc

utf8の扱い

下記のプログラムをutf8で書いてみます。

use strict;
use warnings;


my $str = 'テスト';
print length $str, "\n"; # 9


実行すると「9」が出力されます。length関数は「テスト」をバイトとして扱うので、
返す結果は「3文字」ではなく「9バイト」になるわけです。


次にutf8プラグマを使うとどうなるか。

use strict;
use warnings;
use utf8;

my $str = 'テスト';
print length $str, "\n"; # 3


実行すると「3」が出力されます。
utf8プラグマを使用すると日本語は1文字として扱われるようになるのです。


内部での扱いどうなっているのかというと、utf8かどうかを表すフラグが文字列に付与されています。
このフラグがついているかどうかで、length関数のように扱いが違ってきます。
utf8プラグマは、自動でこのフラグを文字列に付与します。
もし明示的に付与したり、外したりする時は、「utf8::decode」と「utf8::encode」を使用します。

# フラグを付与する
utf8::decode($str);


# フラグを外す
# 何回もencodeするとおかしくなるので、フラグが付与されているかどうか調べる
if (utf8::is_utf8($str) {
    utf8::encode($str);
}


utf8プラグマは、文字列に自動的にフラグを付与するのですが、
これはプログラムに記述されている文字列だけです。
ファイルから読み込んだ文字列やデータベースから取ってきた文字列などは、utf8プラグマの効果が及んでいません。
これらなどには別の処理が必要になります。


ファイル読み込みは下記のように記述すれば良いです。

my $fh;
open $fh, "<:utf8", './example.txt';


データベースに関しては、DBIでのオプション指定でできるみたいです。
MySQLの場合は、下記のようにすれば良いです。

my $dbh = DBI->connect(@args);
$dbh->{mysql_enable_utf8} = 1;


ということで、前回の文字化けには、これで対処できるようになりました。