2007年02月14日 21:30 [Edit]

regexp - yet another fix for dodgy UTF-8

他の言語にも移植しやすいようにrefactorしてみました。

subtech - Bulknews::Subtech - Fix dodgy utf-8 bytes
すでに utf-8 なバイト列を latin-1 と解釈して utf-8 に二重エンコードすることで起きる文字化け(を表現する短い言葉ってないのかな)を直すコード。

sub fix_utf8 {
    my $bytes = shift;
    utf8::encode($bytes) if utf8::is_utf8($bytes);
    $bytes =~ s{
        ([\xC2\xC3])([\x80-\xBF])
    }{
        chr( (ord($1) << 6 & 0xff) | ord($2) )
    }egx;
    $bytes;
}

Encode MantainerがコードをEncodeフリーにrefactorするというのも変だけど、これなら他への移植がずっと楽なので。例えばRubyだと、こんな感じですか。

def fix_utf8(bytes)
    bytes.gsub(/([\xC2\xC3])([\x80-\xBF])/n){
        ( ($1[0] << 6 & 0xff) | $2[0] ).chr
    }
end
string = "小飼" + "\xc3\xa5\xc2\xbc\xc2\xbe"
puts string
puts fix_utf8(string)

Enjoy!

Dan the Encode Maintainer


この記事へのトラックバックURL

この記事へのコメント
コードのわかりやすさ(読めば何をしているかわかる)ということで Encode::encode と decode をつかいましたが、こっちのほうが動作もはやそうですね。Encode::DoubleEncodedUTF8 0.02 としてリリースしました。
Posted by miyagawa at 2007年02月15日 08:14
tociyukiさん、
ありがとうございます。反映させました。
Dan the Occasional Rubyist
Posted by at 2007年02月14日 22:53
Ruby の正規表現リテラルにオプション n をつけると$KCODE に依存せずにバイト単位でマッチングするようになります。 /([\xC2\xC3])([\x80-\xBF])/n
Posted by tociyuki at 2007年02月14日 22:08