- 締切済み
Cannot decode string with wide characters
use utf8; binmode STDOUT, ':utf8'; binmode STDIN, ':utf8'; use strict; use Encode; sub main(){ #UTF-8(BOMなし),CRLFのファイルに書いてます。 my $str = "あ"; my $bin = $str; $bin = Encode::encode('euc-jp', Encode::decode('utf8', $str)); $bin = Encode::encode('utf8', Encode::decode('euc-jp', $bin)); print "Content-Type:text/plain;charset=UTF-8\n"; print "\n"; print $bin; } &main; ======================= 希望する出力結果: あ ============================ 結果:Internal Server Error Apacheのエラーログ: [Wed Jan 09 15:07:34 2008] [error] [client 127.0.0.1] Premature end of script headers: 20080109-1.pl [Wed Jan 09 15:07:34 2008] [error] [client 127.0.0.1] at C:/Environment/Perl/v5.8.8/lib/Encode.pm line 166.\r ========================= 質問: どのように修正すればよいか?
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- sakusaker7
- ベストアンサー率62% (800/1280)
>相変わらず取り払ってもエラーが消えず。 #1の補足にあるスクリプトで試してみましたが、こちらではエラーになりません。 スクリプトは utf-8で保存しています。 binmode をしないと Wide character in print at mmm.pl line 10. という警告が出ますが。
- tao_0077
- ベストアンサー率48% (33/68)
2行目3行目の binmode はいらないんじゃないでしょうか? それはそれぞれ、内部 UTF8(UTFフラグ付き文字列)をそのまま出力(入力)する時に使用するもののようです。 ですから、binmode を使用する場合、内部UTF8文字列をそのまま print 文に渡してやって binmode STDOUT, ':utf8'; my $bin = "あ"; print $bin; で正常表示。 binmode を使用しない場合、内部文字列をいったんUTFフラグを削除して(通常の UTF8 にエンコーディングして) my $bin = "あ"; $bin = Encode::encode('utf8', $bin ); print $bin; で正常表示となるはずです。
お礼
後者が成功しないのは,Content-Type:text/plainを吐いてないのに CGIを利用としたからのようです。 相変わらず取り払ってもエラーが消えず。
補足
>2行目3行目の binmode はいらないんじゃないでしょうか? いけね,文献読んだのに間違えた。 >When you encode, the resulting UTF8 flag is always off. >When you decode, the resulting UTF8 flag is on unless you can unambiguously represent data. Here is the definition of dis-ambiguity. 逆だと思い込んでた。 ============== ・・・けど,2行目と3行目削っても同じエラーが出るんですよ。 Windows XP SP3 RC1(v3264) Apache 2.2.6 Perl 5.8.8 ============ あれ?さっき,成功したと思ったんだけど Prematureどーたらがこれだけでも出るようになっている。 少しちょっと頭冷やしてこよう。 use utf8; use strict; use Encode; binmode STDOUT, ':utf8'; binmode STDIN, ':utf8'; sub main(){ #UTF-8(BOMなし),CRLF my $str = "あ"; print $str; } &main;
お礼
use utf8; use strict; use Encode; #一応「あ」が表示された。 #元々今回の実験は ある文字列を #UTF-8の文字列をEUC-JPにして #もう一回UTF-8にして元通りか比較する,というものだった。 ##元々PHPの別な検証だった。 ##PHPでは,mb_convert_encodingで指定した変換先の ##文字集合に含まれない文字は?に置換されるが, ##これがイヤで。変換できない時は「例外」として「キャッチしたかった」んだ。 ##なので EUC-JPに含まれない文字列を ##リテラルで指定し,UTF-8で戻ってきたときの ##文字列を元の文字列と比較することで, ##エラーを検知しようとしていた。 ###unicode.from_error_mode = U_INVALID_STOPって何のために在るんだろう? ##ただし,Encode::encode関数の仕様によるとperlでは変換できないときundefを返すようなので比較は必要ない sub main(){ #UTF-8(BOMなし),CRLFのファイルに書いてます。 my $str = "あ"; #$binに代入していたことには特に意味はない。 #強いて言えばPHPで検証をしていたときの名残。 #うまくいかなかった理由としては #http://www.perlmonks.org/?node_id=569561 #らしいが,俺は良くは理解できてない。 #このサイト自体は見つけていたが,簡単に読める気しなかったので読まずにスルーしていた。 #締め切るまで一日くらい置くつもりだから #よくわかる解説をしてくれるなり, #(sequence of bytesに変換したらうまく通ることがわかるようなテストケースとか) #何かいいたいことがあるなら言うなり,好きにしてくれ。 #今回はポイントが#1さんに10ptだけで終わるかも。ごめんね。 my $bin; #一応「あ」が表示された。 #以下の一行が違う $bin = Encode::encode('euc-jp',$str); $bin = Encode::encode('UTF-8', Encode::decode('euc-jp', $bin)); print "Content-Type:text/plain;charset=UTF-8\n\n"; print $bin; } &main();
補足
#1のお礼に書いたとおり, ============================================= コマンドプロンプトではなくCGI経由で利用していて, 【#1の補足のソースは】 print "Content-Type:text/plain\n\n"; を追加することで,エラーは発生しなくなっています。 尤も大元の質問は print "Content-Type:text/plain;charset=UTF-8\n"; print "\n"; を何となく print "Content-Type:text/plain;charset=UTF-8\n\n"; にしたという違いはあれど, 2行目,3行目のbinmodeを取り除いても「あ」が表示されておらず、エラーが出ております。 =====================================