CGI(Perl)のページ出力キャラクタをutf8にしたら文字化け

| コメント(0)

MySQL-5.5上に載せてあるデータベースのキャラクタセットで4バイトのunicodeが使える様になったので、調子に乗って、これまでに作ったCGIのページ出力も、EUC-JPからUTF-8に切り替える作業を進めている。

で、うちのサイトでgoogleクローラが最も熱心に拾って行く「今日は何の日?」も去る12月21日(水)に出力キャラクタセットをEUC-JPからUTF8に切り替えた。

昨日ふと見ると、明治5年以前の出来事では和暦の年月日を表示しているのだが、その「xx月」の部分が消えていた。
どうも、PerlでUTF-8を使う際の作法を守らず、ソースコードをUTF-8に変換して、HTMLのMETAタグのキャラクタセット指定をutf-8に変更、 use utf8 行とデータベースから受けた変数に対するutf8::decode行を追加しただけの手抜き対応をしたのがまずかった様である。 \(^o^)/

手抜きすると、やっぱりどこかでボロが出るなぁと思いつつ、こちらのサイトを参考に、Perl上でUTF8を使う際の作法を整理して、プログラムを修正した。
ちなみに、使用しているPerlは、Ver.5.8.8 と、Ver.5.12.4 である。


Perlのutf8フラグを意識して、一通り、utf8::encode(utf8フラグOff)、utf8::decode(utf8フラグOn)、no utf8 行で体裁を整えたのだが、状況は改善しなかった。

仕方が無いので、テストプログラムを組んで試してみた処、次の様な結果になった。ソースコードはUTF-8で記述している。

サンプル1

ソースコード

#!/usr/bin/perl

use utf8;

my($string) = '12';
binmode STDOUT => ":utf8";
if($string eq '1u'){
print "閏1月\n";
}else{
print "$string月\n";
}
print length($string), "\n";

実行結果


2

サンプル2

ソースコード

#!/usr/bin/perl

use utf8;

my($string) = '12';
binmode STDOUT => ":utf8";
if($string eq '1u'){
print "閏1月\n";
}else{
print "$string"; # ←Latin-1の文字列が入る変数直後でprint文を分離
print "月\n";
}
print length($string), "\n";

実行結果

12月
2

以上の結果で推測されるのは、Latin-1(UTF-8でもあるハズ)の“12”と、UTF-8の“月”が、誤った1文字として処理されてしまっているようだ、ということである。

正直な感想として、この様なものに起因する「文字化け」は、原因に辿たどり着くのが難しいだろうと思う。
先の記事にもあったが、正に

スクリプト内に8bitのバイト列がある(たとえば、文字列リテラルに、Latin-1がある)なら、 "use utf8" は、不幸をもたらすでしょう。バイト列は、ほとんどの場合、適切なUTF-8ではないからです。
を地で行っている感じである。

こんな訳で、くだんのページの不具合は、print文の分割で解消できた。
UTF-8は文書の記述に便利な反面、プログラムを組む際には注意が必要だと、改めて感じた次第である。


(追記)

同様の不具合を回避する方法として、もっとスマートなものは無いだろうかと考えてみたのだが、 print 文は no utf8 を宣言したスコープ内で実行するしかない様な気がする。折角UTF-8でソースを書いて、UTF-8で入出力しようとしても、プログラム中で出力部分は no utf8 では、ちょっと残念な感じが否めない。

なんとかならないものだろうか。

コメントする

このブログ記事について

このページは、山椒魚が2011年12月27日 12:36に書いたブログ記事です。

ひとつ前のブログ記事は「FreeBSD セキュリティ勧告 FreeBSD-SA-11:10.pam」です。

次のブログ記事は「ダサい」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

おすすめサイト

おすすめ

サーバ/OS技術書

技術書一般

  • 長沢工:天体の位置計算 増補版

    長沢工:天体の位置計算 増補版

    天体の視位置を計算する「位置天文学」の入門書。ロングセラー。刊行が古いために、具体的計算に使われている星表等の定数は、1984年以前の計算システムによるものである。しかし、現在、新刊で入手可能な同種の書籍は限られており、天体位置計算の考え方が変った訳ではないので、現在でも充分に役立つだろう。

いろいろ