December 02, 2003

Perl Tips: Unicode 文字列

Perl 5.6 以降では、文字列に Unicode フラグというのがつきます。
XML など文字コードを明示的に指定した場合などは Unicode 文字列として扱われ、length などが文字セマンティクスで動作します。

ある変数に Unicode フラグがたっているかどうかは、Devel::Peek モジュールでわかります。

use Devel::Peek;
Dump $s

ここで問題になるのが、文字列連結での自動アップグレード問題といわれるもので、内部的に Unicode フラグがたっている文字列と、そうでない文字列を連結すると、自動的にそうでないほうが Unicode にアップグレードされます。ここが文字化けの原因になります。

1. テンプレートを UTF-8 で記述し、Template-Toolkit で読み込み
2. DB は MySQL に UTF-8 に格納して DBD::mysql で取り出し
3. ローカルの RSS ファイルを XML::RSS でパースして取り出し

とやってつなげると、すべて UTF-8 なバイト列なのですが、3. だけに Unicode フラグがたちます。最後に結合するときに1. と 2. が自動アップグレードされて化けます。

5.8 であればファイルハンドルに binmode とかやったりして適切に Unicode フラグたてられますが 5.6 ではそうもいきません。またこの例のように、TT や DBI など、モジュール内部で文字列が作られていじれない場合もあります。

というわけでこういうときは 3. から UTF-8 フラグを外してやるのがてっとりばやいです。
5.8 では use utf8; utf8::downgrade($s);、5.6 では pack('C*', unpack 'C*', $s); のようにすればとりあえずフラグは外れます。

参考: Perl の Unicode Support

Posted by miyagawa at December 2, 2003 04:50 PM | Permalink | Comments (1) | TrackBack(2)
Comments

Jcode.pmのインターフェースを持った
Encode.pmのラッパーを書いていたのですが、
trがうまく動作せずに悩んでいました。
この記事のおかげでDevel::Peekを使って
確認すればいいことを知り、解決しました。
ありがとうございます。

Posted by: まかまか on December 6, 2003 01:55 PM
Trackbacks
TrackBack URL for this entry: http://blog.bulknews.net/mt3/mt-tb.cgi/588
MTISBN
Excerpt: http://www.asmate.net/software/perl/mt-isbn/ http://siteas.net/usemod10/wiki.pl?DownLoads MTISBNをいれてみました。 するとこんなかんぢに表示されます。 ISBN: 4048970410 やっと文字化けするBugが取れた……UTF-8の問題でした。UTF8のフラグの問題で、フラグ付きU...
Weblog: Bstyle = LOlita + Goth
Tracked: June 10, 2004 12:58 AM
[プログラミング] PerlのEncodeについて
Excerpt: ある変数に Unicode フラグがたっているかどうかは、Devel::Peek モジュールで わかる。 use Devel::Peek; Dump $s なるほど。
Weblog: 根岸の未来計画とその過程
Tracked: January 17, 2006 02:46 PM
Post a comment