Perl utf8モジュールの効果と文字化けについて


Perl言語を活用しまして、外部サイトのRSSファイルを取得し、その取得したRSSの内容を当方のサイトに出力したいと思っております。
RSSを取得するモジュールとして「XML::FeedPP」というモジュールを活用します。(http://www.kawa.net/works/perl/feedpp/feedpp.html
今回の質問はutf8モジュールを使用したときに特定の条件で文字化けがおきる理由が知りたいということです。
以下に、RSSファイルを取得しサイトに出力する4つのケースを記述します。(すべてUTF8コード)

ケース1、http://nichista.seesaa.net/image/case1.txt
ケース2、http://nichista.seesaa.net/image/case2.txt
ケース3、http://nichista.seesaa.net/image/case3.txt
ケース4、http://nichista.seesaa.net/image/case4.txt

さて、途中の13行目から「#ケース1~4)」の部分を変更して複数の条件でプログラムを走らせます。
上記の4つのケースのうち、「ケース3」のみ文字化けしてしまいます。
しかし、なぜ「ケース3」だけこのような文字化け現象がおきるのでしょうか?
この現象の理由を知りたく存じます。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2011/10/28 12:08:52
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:windofjuly No.1

回答回数2625ベストアンサー獲得回数1149

ポイント300pt

外部のページを参照するのは面倒なので、まずは1つにまとめさせてもらいました

#!/usr/bin/perl
use utf8;
use strict;
use XML::FeedPP;

print "Content-type: text/html\n\n";
print "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html\; charset=UTF-8\"><title>test</title></head><body>\n";
my $source = 'http://www.nicovideo.jp/ranking/fav/daily/g_popular?rss=2.0';
my $feed = XML::FeedPP->new( $source );
print "Title: ", $feed->title(), "<br />\n";
foreach my $item ( $feed->get_item() ) {

#ケース1
	print "Title: ", $item->title(), "<br />";
#ケース1

#ケース2
	my $stock = $item->title();
	print "Title: $stock<br />";
#ケース2

#ケース3
	my $stock = $item->title();
	print "タイトル: $stock<br />";
#ケース3

#ケース4
	my $stock = $item->title();
	utf8::decode($stock);
	print "タイトル: $stock<br />";
#ケース4

}
print "</body></html>\n";
exit;

 

さて、本題への答えですが、外部から読み込んだものは、

そのキャラクタセットなどには一切関知せず、

「そのままの形」で保持されていることが原因となっています

 

対処例から述べますと、use open IN などで、

「外部から読み込んだものはutf-8として取り扱う」といった、

フラグを立てるようにするなどします

 

ケース1および2では、

Titleという半角英数字との組み合わせであるために、特に問題は発生せず、

ケース4においては、

単独でフラグを立ててやってますので、これまた問題は発生せず、

問題のケース3では、

日本語との組み合わせになっているため、

そのままの形でつかってくれれば良いものを・・・

気を利かせて(というのは言葉のアヤですが)変換しようとしてしまうようなのです

 

参考

http://www.rwds.net/kuroita/program/Perl_unicode.html

id:windofjuly

追記:

ブラウザによっては、HTMLのMETAタグにだけUTF-8などと指定しても、

正常にキャラクタセットを認識できない場合があるため、

httpヘッダーでもキャラクタセットを指定しておくほうがベター

2011/10/22 14:04:54
id:nagato-yuki

ご回答、及び追加コメントありがとうございます。

なるほど、外部読込みの場合は文字コードを関知せずに、

そのままの形で取り込まれているのですね。

結果、utf8モジュールを使用しutf8フラグを立てないままでは

「ケース3」の場合、マルチバイトと認識せずにシングルバイトとして認識・出力されてしまう、ということが理解できました。

わがままで恐縮ですが、もう少し詳しくご教授いただきたい部分がございます。

ケース3では、”タイトル:”という文字列にフラグが立っているため、後のフラグなし変数をシングルバイト変換してしまうことが分かります。

それでは、ケース2の場合、utf8モジュールは”Title:”という文字列にフラグを立てず、後の変数もそのままの形で出力している、ということなのでしょうか?

print "(半角英数)+(日本語を含む変数)"; (ケース2)

print "(日本語)+(日本語を含む変数)"; (ケース3)

(半角英数)(日本語)にフラグが付くかどうかによって、後の(日本語を含む変数)にutf8モジュールがどのような判断をしているのでしょうか?

度々の質問で申し訳ございませんが、お答えいただけると幸いです。

2011/10/23 12:17:46

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません