2009年09月13日 13:00 [Edit]
#perl - utf8::decode()ではなくEncode::decode_utf8()を使うべき理由
駄目です。
[を] Perl の utf8 まわりのおまじない最近良く使うおまじない、というかイディオム。utf8::decode($text) unless utf8::is_utf8($text);
こういう場合は、Encode::decode_utf8()でないと。
以下をごらんください。
#!/usr/bin/perl
use strict;
use warnings;
use Encode;
use Devel::Peek;
for my $bytes ( "\x2F", "\xC0\xAF", "\xE0\x80\xAF", "\xF0\x80\x80\xAF" ) {
my $utf8 = $bytes;
utf8::decode($utf8) unless utf8::is_utf8($utf8);
Dump($utf8);
}
から持ってきた例題ですが、見ての通り、utf8::decode()は、不正なUTF-8バイト列に対して何もしません。
今度はEncode::decode_utf8()を見てみましょう。
#!/usr/bin/perl
use strict;
use warnings;
use Encode;
use Devel::Peek;
for my $bytes ( "\x2F", "\xC0\xAF", "\xE0\x80\xAF", "\xF0\x80\x80\xAF" ) {
my $utf8 = decode_utf8 $bytes;
Dump($utf8);
}
今度は不正な文字は、全て\x{fffd}、REPLACEMENT CHARACTERに置き換えられています。
Validationの観点だけではなく、簡潔性の観点からも、Encode::decode_utf8()はおすすめです。すでに UTF-8 flag がついた文字列はそのままコピーするだけなので、条件分岐も不要です。
#!/usr/bin/perl
use strict;
use warnings;
use Encode;
use Devel::Peek;
{
use bytes;
my $bytes = '小飼弾';
Dump($bytes);
my $utf8 = decode_utf8($bytes);
Dump($utf8);
}
{
use utf8;
my $bytes = '小飼弾';
Dump($bytes);
my $utf8 = decode_utf8($bytes);
Dump($utf8);
}
utf8.pmのPODにもこうあります。
$success = utf8::decode($string)Attempts to convert in-place the octet sequence in UTF-X to the corresponding character sequence. The UTF-8 flag is turned on only if the source string contains multiple-byte UTF-X characters. If $string is invalid as UTF-X, returns false; otherwise returns true.
Note that this function does not handle arbitrary encodings. Therefore Encode is recommended for the general purposes; see also Encode.
utf8::decode()は、定数文字列、すなわちソース内の文字列に限って利用すべきでしょう。外部入力はEncodeに振りましょう。
Dan the Encode Maintainer
この記事へのトラックバックURL
これは知りませんでした。
弾さん書くしかないでしょう。