utf8

perl ソースの文字列リテラルに(必要であれば)utf8フラグをセットする。

use encoding "utf8"; とほぼ同じであるが、no utf8; によって動的に use utf8; を無効にすることができる。但し、文字列リテラルにのみ影響し、既に変数に代入されている文字列には影響を及ぼさない。
また、文字列がワイド文字を含まない場合は、常にutf8フラグはセットされない。

length や substr などの文字列操作関数は、utf8フラグがセットされた文字列を正しく1文字を1文字として扱う。utf8フラグなしの文字列は1文字1バイトと仮定して操作される。

utf8フラグ付きの文字列とutf8フラグなしの文字列が混在すると文字化けが発生したり、文字列置換でバグが発生するので、use utf8; で正しくプログラムする為には、いくつかの注意点がある。

*ファイル出力をutf8モードにする。
use open IO => ':utf8';

ファイル入力をutf8モードにしないと、読み込まれた文字列にはutf8フラグが付かない。一時的に生のファイル内容を読み込みたいならば、ファイルをオープンした後、binmode(HANDLE,":raw")を実行する。
ファイル出力をutf8モードにしないと、ワイド文字出力時に警告が表示される。

*標準出力をutf8モードにする。
binmode(STDIN,':utf8');
binmode(STDOUT,':utf8');
binmode(STDERR,':utf8');

標準入力をutf8モードにしないと、読み込まれた文字列にはutf8フラグが付かない。
標準出力をutf8モードにしないと、ワイド文字出力時に警告が表示される。

*文字列の変数展開
utf8フラグがONされる文字列リテラル内で変数展開を行なうとコンパイルエラーになる。
例えば:
"漢字文字列:$string"  → エラー
"漢字文字列:" . $string → OK
"wide character:$string" → OK($stringがutf8文字列でもOK)

*CGI
use CGI qw(-utf8);

ブラウザから受け取った文字列に自動的にutf8フラグをセットする。

*DBI
my %attr = (
    pg_enable_utf8 => 1       # postgreSQLの場合
    mysql_enable_utf8 => 1   # MySQLの場合
);
$handle = DBI->connect($dbname,$dbuser,$dbpass,\%attr);

DBから読み出した文字列に自動的にutf8フラグをセットする。

*HTML::Template
my $template = HTML::Template->new(
   filename => 'file.tmpl',
    utf8 => 1
);

テンプレートソースやパラメータ内の文字列はutf8フラグONであると仮定して扱われる。

*Log::Log4Perl
Log::Log4perl::Appender::Fileの場合:
    log4perl.appender.<appenderID>.utf8=1
Log::Dispatch::FileRotateの場合:
    log4perl.appender.<appenderID>.binmode=:utf8

ログ出力する文字列はutf8フラグONであると仮定して扱われる。

*Test::More
use Test::More;
use Test::More::UTF8;

diagでutf8フラグONの文字列を表示した時に警告を表示しないようにする。


utf8フラグは下記のユーティリティ関数で操作できる。

utf8::encode($string);
utf8フラグをOFFにする。文字コードセットを変換は行わない事に注意。
二重エンコードすると文字化けする。事前にutf8フラグのチェックが必要。

$success = utf8::decode($string) ;
utf8フラグをONにする。文字コードセットを変換は行わない事に注意。
二重デコードしても文字化けしない。事前のutf8フラグのチェックは不要。
不正なutf8文字列を渡すと、$successに0が返る。

$flag = utf8::is_utf8($string);
utf8フラグがONならば、trueを返す。

$flag = utf8::valid($string);
正しいutf8表現であれば、trueを返す。正しいutf8表現とは、utf8フラグがONであり、正しいutf8で構成される文字列である。