• ベストアンサー

guess_encoding()の挙動が意味不明

Wernerの回答

  • Werner
  • ベストアンサー率53% (395/735)
回答No.3

> 毎回同じ文字化けを起こしてしまうのは何故なのでしょう。 「if($check==1)」の手前あたりにでも | print ref($decoder) ? $decoder->name : $decoder; | print "\n"; と書いてみてください。 1つめ以外は全てUTF8であると判定されていることが分かると思います。 (これはUTF8フラグを立てる以外何もしないdecoderです。) また、判定に失敗しているのは、UTF8かそれ以外のどちらかであるという 推測結果になっているからだと言うことも分かります。 guess_encodingの第2引数には、何も指定しなくても asciiとutf8をデフォルトで指定したのと同じ事になります。 つまり、1つだけをguessの候補にしたつもりが 実はそうなっていなかったという事です。 なので私がNo.1で触れたように、推定候補は全てまとめて渡すべきでしょう。 > 日本でよく用いられている文字コードは >  shift-JIS、EUC-JP、JIS > です。 中国の事情はさすがに知りませんが、 日本においてもShift-JISとそっくりな CP932(Microsoftコードページ932、Windows-31Jとも呼ばれる)という文字コードが存在します。 CP932はWindowsで日本語を扱うために使われてきた文字コードですが これが良くShift_JISと呼ばれているため、 一般にShift_JISと呼ばれている文字コードのほとんどは実際にはCP932だったりします。 Shift_JISとCP932ではUnicodeとのマッピングが異なるため、 両者を混同すると「WAVE DASH - FULLWIDTH TILDE問題」として知られる 文字化けの原因になったりするのですが、 その辺の事情を知らないとどっちを使ったらよいかなんてまず分からないですからね。 なので、日本語の事情でも結構面倒なところはあります。 > なんでHPともCGIとも関係の無い文字コードがCGIに送り込まれてくるのか 私は知らなかったのですが、検索したらこんなのが見つかりました。 (個人的には無視しても良い気もします。 広範なコードポイントを含むUTF8が別の文字コードにされるようなことがもしあれば 情報が欠落してしまうのは防ぎようがないですし。) 予期しない文字コードでPOSTされるケース http://www.shtml.jp/mojibake/mac_post.html 文字コード判定の話に戻りますが、 判定が確実に出来ないのは元の文字列が何か分からないことが大きいので、 隠しテキストボックスにでも適当な(既知となる)文字列を入れておいて 一緒にPOSTされるようにしておけば、 判定精度を高めることは出来ると思います。 (既知文字列を候補文字コードでencodeした結果とPOSTデータを比較してチェックする。)

makoji
質問者

補足

>1つめ以外は全てUTF8であると判定されていることが分かると思います。 ものの見事に最初にヒットした文字コード以外皆UTF-8になっていますね。 でもまだよく分からないんです。 >guess_encodingの第2引数には、何も指定しなくても >asciiとutf8をデフォルトで指定したのと同じ事になります。 >つまり、1つだけをguessの候補にしたつもりが >実はそうなっていなかったという事です。 元のプログラム中のD式   $decoder=guess_encoding($j,$i); は字面的には$iだけを文字コードの候補としていますが、この他にasciiとutf8がデフォルトで候補になっている。 これが本当なら、foreach文で全ての文字コードを検証したのですから、@dataはutf8に書き換えられているのだし、全ての文字コードでutf8がヒットしてしまい、$check=0となることは最初のヒット以降ないはずです。 でも実際には、最初のヒット以降も$check=0となる文字コードは出現していますから、guess_encoding()の第2引数を指定した場合、デフォルトのascii、utf8は候補から外れているのではないかと思えます。 その一方でascii、utf8が候補から外れているなら$decoderをprintした時にutf8が書かれるというのはおかしいです。 なんか釈然としません。 >隠しテキストボックスにでも適当な(既知となる)文字列を入れておいて >一緒にPOSTされるようにしておけば、 >判定精度を高めることは出来ると思います。 良いアイデアですね。ありがとうございます。

関連するQ&A

  • デコード処理について

    いつもお世話になっております。 Perlのデコード処理で分からない事があります。 大変申し訳ございませんが、 ご存知の方がいらっしゃれば、教えて頂けますでしょうか。 以下のプログラムを実施すると以下のエラーが発生しまい 正しくデコードされた結果が表示されません。 この場合、どのようにして$sの文字をUTF-8と判断させて shiftjisに変換すればよいのでしょうか? (プログラム) #!/usr/local/bin/perl use Encode qw/from_to/; use Encode::Guess; Encode::Guess->set_suspects(qw/shift-jis euc-jp 7bit-jis/); $s = '%E7%A7%BB%E8%BB%A2'; # UTF-8 $s =~ tr/+/ /; $s =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2", $1)/eg; my $decoder = Encode::Guess->guess($s); die $decoder unless (ref($decoder)); &from_to( $s, $decoder->name, "shiftjis" ); print $s; (エラー内容) shiftjis or euc-jp or utf8 at test.pl line 12.

  • WWW::Mechanizeの文字コードについて質問

    WWW::Mechanizeの文字コードについて質問 以下のようなソースコードを書いて実行してみたのですが どのサイトを取得しても、すべて文字コードがUTF8だと認識されます。 ------------------------------------------------------- #!/usr/bin/perl #WWW:MechanizeでHTMLの取得 use WWW::Mechanize; $w = WWW::Mechanize->new(); $w->get("URL"); $html=$w->content; #文字コードの判別 use Encode; use Encode::Guess qw/ascii utf8 euc-jp shiftjis 7bit-jis/; my $dec = Encode::Guess->guess($html); print$dec->name; ------------------------------------------------------- 例えば以下のサイトは文字コードがEUC-JPですがこれもprintされるのはUTF8となってしまいます。 http://barukanlog.blog31.fc2.com/blog-entry-541.html WWW:Mechanizeでサイトを取得し、サイトの文字コードを調べてすべてsjisにする ということがしたいのですが、すべてutf8に判断されて先へ進めないんです。 何か設定やメソッドを追加しなくてはいけないのでしょうか? わかりにくい質問かとは思いますがご回答お願いします。

  • Perl 文字コードについて

    From: $from To: $mailto CC: $mailcc Subject: $subject Mime-Version: 1.0 Content-type: text/plain;charset=\"UTF-8\" Content-Transfer-Encoding: 8bit この時点で、UTF-8を指定しました。 use Encode; use Encode::Guess; Encode::Guess->set_suspects( qw/ euc-jp shiftjis 7bit-jis / ); $name = encode('UTF-8', decode('Guess', $name)); で本文を、UTF-8に変換して送るようなコードを書きました。 これで一応、パソコン、スマホ共に「本文」は文字化けせず送れるのですが、 今度、別の問題が発生してしまったようで、 「件名」が文字化けしてしまうようになりました。 $subject = encode('UTF-8', decode('cp932', $subject)); 件名も、本文と同じように変換コードをしてみたところ、パソコンでは文字化けしませんでしたが「件名」で文字化けしてしまいます。 調べたところ本文と件名では、内容が違い MIMEエンコードを使用するとのことだったのですが、 実際どのように使うのかわからないです。 $subject = encode('ISO-2022-JP', decode('cp932', $subject)); encode('MIME-Header-ISO_2022_JP', $subject) このように記述するとスマホでは文字化けしないのですが パソコンで文字化けしてしまいます。 そこで、件名がパソコンとスマホで文字化けしないようにし、本文はUTF-8で送るようにするにはどのようにすればいいのでしょうか?

    • ベストアンサー
    • Perl
  • JcodeモジュールとEncodeモジュール

    以下、Perl5.8でJcodeモジュールを使った場合とEncodeモジュールを使った場合の違いについて、知りたいです。 ※そもそもこのモジュールは同時に使ったらだめなのでしょうか? use strict; use utf8; use Jcode; use Encode; my $dat1 = "あイ卯(1)Iⅰ"; Jcode::convert(\$dat1, "utf8"); my $dat2 = "あイ卯(1)Iⅰ"; $dat2 = Encode::encode("utf8", $dat2); 文字コード変換の正しい使い方が知りたいです。

    • ベストアンサー
    • Perl
  • Encode と encoding の同時使用で ISO-2022-JP に encode できない

    CentOS を 5.1 から 5.2 にアップデートした頃から PerlCGI からのメール送信が出来なくなって、調べていたら「ISO-2022-JP への encode がおかいぞ問題」に辿り着きました。 以下のコードで、euc-jp が吐かれてしまいます。 #! /usr/bin/perl -w use encoding('UTF8'); use Encode; binmode(STDOUT); my $text = "<全角文字ですよぉ。>"; print encode('ISO-2022-JP', $text), "\n"; 以下のいずれかで正常に jisコードを吐く様になるのですが、こんなものなんでしょうか? 1 「use encoding('UTF8');」 を 「use utf8;」に替える 2 print の直前に "no encoding;" を入れる CentOS 5.1 では多分正常に ISO-2022-JP への変換ができていたのだと思います。 私の使用するバージョンの Cygwin の Perl でも正常です。 問題のある CentOS5.2 と 問題の無い Cygwin版で、関係しそうなバージョンの違いはありません。 CentOS 5.2: Perl 5.008008 Encode 2.12 Encode::JP 2.01 encoding 2.02 Cygwin: CYGWIN_NT-5.1 **** 1.5.25(0.156/4/2) 2008-04-17 12:11 i686 Cygwin Perl 5.008008 Encode 2.12 Encode::JP 2.01 encoding 2.02 できれば、すでに動いているCGIの use encoding('UTF8'); を直す事なく動く様にしたいのです。

  • 文字コードの変換(Shift-JISからUTF8)

    文字コードがShift-JISのCSVファイルを読み込み、UTF-8のテキストファイルに出力するのに プログラムの中で変更しようとしているのですが、うまくいきません。出力ファイルの文字コードを 確認するとShift-JISのままです。 どなたか教えていただけないでしょうか? ActivePerl v5.16.0を使用し、Encodeモジュールのfrom_toを使用しています。 #!/usr/bin/perl use strict; use warnings; use utf8; use Encode; my $input_file="input.csv"; my $output_file="output.txt"; open (IN, $input_file) or die "$!"; open (OUT, ">$output_file") or die "$!"; while (<IN>){ chomp ($_); my @data=split(/,/,$_); for(my $i=0;$i<@data;$i++){ $data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換 $data[$i]=~s/\s+//g; print OUT $_; } print OUT "\n"; } close (IN); close (OUT);

    • ベストアンサー
    • Perl
  • Perlの文字コード変換についての質問です。

    Perlの文字コード変換についての質問です。 ホームページ全体は、UTF-8で作成されています。 そのため、$qsは、どうも、S-JISのようなので、UTF-8に変換して URLデコードさせたいのですがうまくいきません。 文字化けしないで、UTF-8で作成されたページに表示させたいのですがどうすればよいでしょうか? 宜しくお願い致します。 ------------------------------------ $qs = $ENV{'QUERY_STRING'}; use Encode::Guess qw/ shiftjis /; use Encode qw/ decode /; $enc = guess_encoding ( $qs ); if ( ref $enc ) { $utf8 = decode ( $enc->name , $qs ); } $qs =~ tr/+/ /; $qs =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg; print "$qs";

    • ベストアンサー
    • Perl
  • Encodeについて

    いつもお世話になっております。 下記の構文で分からないところがございます。 use Encode; use Encode::Guess qw/euc-jp shiftjis 7bit-jis/; use Encode qw/decode/; $enc=guess_encoding($x); if(ref $enc){$x=decode($enc->name,$x);} 実はあるテキストに載っていたコードなのですが、解説には 文字データのコードが分からない場合は、Encode::Guessを使います としか書いてありません。 2行目は、文字コードのリストをqwで囲んであると分かりますが 3行目は、なぜdecodeをqwで囲む必要があるのでしょうか。 decodeメソッドを使うと意味だとすると、必要ないように思ってしまい ました。大きな勘違いをしているかもしれません。 最後の2行は、文字コードを推測して、そのあとが分かりません。 いつも初心者質問で申し訳ありませんが、よろしくお願いいたします。

  • [Perl]Shift-JISのXMLを解析する場

    行き詰まってしまったので教えて下さい。 <やりたいこと> とあるAPIからXMLファイルを取得し、解析して出力する、ということをやっているのですが、元のXMLがShift-JISでエンコーディングされており、これをUTF-8に変換して出力しようとしています。 <問題> XMLを取得して解析、取り出したいパラメータが出力できるようにはなったのですが、文字のエンコーディングが上手く行っていないためか、文字化けしてしまいます。 <元のXML> <?xml version="1.0" encoding="Shift_JIS"?>  <test>   <prod count=3>    <record>     <code>アイウエ</code>    </record>    <record>     <code>カキクケ-</code>    </record>    <record>     <code>ABC</code>    </record>   </prod>  </test> <XML解析用のコード> #!usr/bin/perl use utf8; use Encode qw/ from_to encode decode /; use Encode::Guess qw/ euc-jp shiftjis 7bit-jis /; use LWP::UserAgent; use XML::Simple; use Data::Dumper; #--XML取得部分省略 #--XMLはgetで$xmlに格納 $from = guess_encoding($xml)->name; &from_to($xml,$from,"utf8"); $XML::Simple::PREFFERRED_PARSER = 'XML::SAX::PurePerl'; $xs = new XML::Simple(); $ref = $xs->XMLin($xml); $xml =~ s/<\?.*\?>//; for($i=0;$i<=$#{$ref->{'test'}->{'prod'}->{'record'}};$i++){  $name = $ref->{'test'}->{'prod'}->{'record'}[$i]->{'code'}; $name = encode('utf-8',$name); print "$i : $name\n"; } <結果> 黒ダイヤに?文字で文字化けして出力される。 どなたか原因がお分かりになりますでしょうか。 よろしくお願いいたします。

  • UTF-8で書かれたHTMLファイルをShift-JISのファイルに変換できない

    #!/usr/bin/perl -w =begin comment OS: Windows XP Perl: Active Perl v5.8.8 スクリプトは「Shift-JIS」で書いています。 日本語処理関係で参考にしているのはもっぱらオライリージャパンの「Spidering Hacks」の付録の翻訳者 による日本語処理の解説です。 http://oshiete1.goo.ne.jp/qa3716434.html の回答に従い、use encoding 'shiftjis'; から use encoding 'cp932'; へ変更している以外は そこに書かれているやり方に従っていると思います。 UTF-8で書かれたHTMLファイルを「LWP::UserAgent」で取得し、それを Shift-JISコードで出力したいと思い以下のコードを実行したのですが、 以下のエラーが出てしまいました。 Parsing of undecoded UTF-8 will give garbage when decoding entities at C:/usr/local/site/lib/LWP/Protocol.pm line 114. このエラーは何が原因なのでしょうか? =end comment =cut use strict; use LWP 5.64; use Encode; use encoding 'cp932'; # http://oshiete1.goo.ne.jp/qa3716434.html の回答に従い、'shiftjis'から'cp932'へ変更。 #use encoding 'shiftjis'; binmode(STDERR, ':raw :encoding(shiftjis)'); my $url = "http://www.audiounion.jp/bin/products/used/A0/-/-/"; my $browser = LWP::UserAgent->new; my $response = $browser->get( $url ); die "cannot get $url:", $response->status_line unless $response->is_success; my $content = Encode::decode('utf8', $response->content); print $content;