• 締切済み

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
  • 回答数2
  • ありがとう数5

みんなの回答

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

まず情報の訂正から。 > Encode::decode とか Encode::encode のように修飾した名前を使わなければならないところで > decode や encode のように記述できるようになります。 と書きましたが、Encodeの場合はちょっと事情が複雑でした。 use Encode; とした場合 Encode::decode のような修飾なしで関数を呼び出せる。 use Encode qw(decode); とした場合 qw()の中に書かれた関数は修飾なしで呼び出せるが、 それ以外の関数は修飾した名前でないとエラーになる。 つまり上の例の場合、 deocde(ほげほげ)→OK encode(ほげほげ)→NG Encode::encode(ほげほげ)→OK のようになります。 わたしが良く見るモジュールでは前回書いたように、 qw で後に並べた名前だけ修飾なしで使えるというものがほとんどだったと思います。 次に、#1の補足にある > 結果は > こんにちは > shiftjis or utf8 >でした。 geuss_encodingがこれを返したということは、 shiftjis か utf8 のどちらかだと思われるが情報が少なくて決定できない。 ということです。 Encode::Guess によるエンコーディングの判定は Jcodeのものよりもより汎用的にできているため、 データが少ない場合の推測結果があまり正確でなかったり、 今回のように決定できないということになったりします。 もし日本語のエンコーディングだけ推測できればいい ということであれば、Jcodeを使ったほうが自動判定は成績が良い傾向にあります。 http://blog.livedoor.jp/dankogai/archives/50737353.html あたりにちょっと事情が載っています。 対策としてはできるだけ長い文字列を与えて判定させるようにするくらいですかねえ。

nekotora
質問者

お礼

sakusaker7さん、アドバイスありがとうございました。 文字列が少ないと判別に失敗したり、複数行ある場合、1行ずつ 異なるコードと判定したりするようですね。 推測(guess)できなかったときの処理をきちんとしておく必要が あるという結論でしょうか。 Encodeについては、以前にもこのサイトで質問させて頂きました。 私自身は、HTML担当でPerlは勉強中です。文字化け対策としては HTMLも、Perlプログラムも全てutf-8で保存する、コンテントタイプ ヘッダで宣言もするというのが一番の解決と思っています。 それでも化けることがあると聞いたことがありますが・・・ もっと勉強しないとスキルアップできませんね。 お忙しいところ誠にありがとうございました。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

> 3行目は、なぜdecodeをqwで囲む必要があるのでしょうか。 > decodeメソッドを使うと意味だとすると、必要ないように思ってしまい > ました。大きな勘違いをしているかもしれません。 ためしに、 > use Encode qw/decode/; のqw/decode/ の部分を削除して実行してみてください。 > if(ref $enc){$x=decode($enc->name,$x);} の部分で、mainパッケージにdecodeなんて関数ないよという 感じのエラーになるはずです。 つまり、use Encode の後ろにリストで関数名を渡しておくと、 本来なら Encode::decode とか Encode::encode のように修飾した名前を使わなければならないところで decode や encode のように記述できるようになります。 > 最後の2行は、文字コードを推測して、そのあとが分かりません。 > $enc=guess_encoding($x); > if(ref $enc){$x=decode($enc->name,$x);} guess_encodeingが返しているのは、推測によって得られたエンコーディングの情報です。 そして、$enc->name は何かというと、その結果のエンコーディング名です。 つまり、'euc-jp' とか 'utf-8' のようなものです。 ですのでdecodeの第一引数として渡すことができるわけです。 また、ref $enc のようなチェックをしているのは、 適当なエンコーディングに決められなかった場合に、guess_encodingの戻り値は リファレンスではないので、それによりdecode可能かどうかを判定しているためです。 #Encode::Encodingのオブジェクトじゃなかったかなあ。 ですので、decodeのところはオブジェクトのそれを活かして if(ref $enc){$x = $enc->decode($x);} でも同じ結果になったと思います。

nekotora
質問者

お礼

sakusaker7様 丁寧な答ありがとうございます。 decodeメソッド、encodeメソッドは、use Encode; と記述すれば使えるのではないかと思っていました。 例えば use Encode; my $data="shift_jisで書かれた文字列"; $data=decode("shift_jis",$data); $data=encode("utf-8",$data); というような場合とは異なるということでしょうか。 ダブルコロンは、以前 use CGI; $CGI::POST_MAX=1024; で使用したことがありますが、こっちは理由がよく分かりました。 今回の場合は、「?」だったのです。 中途半端なコメントで申し訳ありません。 睡魔のため頭が働かないので、また明日改めてコメントします。

nekotora
質問者

補足

こんにちは。質問者です。 やっと実験できました。下記のように書いてアップロードしてみました。 結果は  こんにちは  shiftjis or utf8 でした。 use Encode qw/decode/; → これは、なくても動いたようです。 でも内容については、実際にいろいろ試してみて やっと分かってきました。 お騒がせして申し訳ありません。ありがとうございました。 use Encode; use Encode::Guess qw/euc-jp shiftjis 7bit-jis/; my $x="こんにちは"; my $enc=guess_encoding($x); if(ref $enc){$x=decode($enc->name,$x);} print <<END; Content-type: text/html; charset=utf-8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>サンプル</title> </head> <body> <p>$x</p> <p>$enc</p> </body> </html> END

関連するQ&A

  • 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
  • デコード処理について

    いつもお世話になっております。 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.

  • 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
  • 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'); を直す事なく動く様にしたいのです。

  • 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]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"; } <結果> 黒ダイヤに?文字で文字化けして出力される。 どなたか原因がお分かりになりますでしょうか。 よろしくお願いいたします。

  • Encode.pmで「髙」(ハシゴ高)が文字化けする

    Perl5.8で、EUCで保存されたテキストファイルを読み込み、Shift-JISで保存しようとしてます。 EUCからShift-JISへの変換は、Encode.pmを使用しています。 テキストファイルに「髙」(ハシゴ高 0xFCE2)や「﨑」が入っていた場合、変換されたデータは「?」(0x3F)になってしまいます。 「髙」や「﨑」をPerlを使用してEUCからShift-JISする方法はありませんでしょうか? ====================================== use Encode qw/ from_to /; open IN, "data.txt"; $data = <IN>; close IN; from_to( $data, 'euc-jp','shiftjis'); open OUT, ">data2.txt"; print OUT $data; close OUT; ====================================== 宜しくお願いします。

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

    ActivePerl-5.14を使っているのですが、文字コードの変換はどのようにすればいいのでしょうか。 ローカル環境で動かしているのですが、Shift-JISのテキストを読み込んで、EUC-JPに変換したいと思っているのですが、 今まで5.8を使っていたので、Jcodeを使って、&Jcode::convert(\$txt,'euc'); としていたのですが、5.14ですと use Jcode;  の時点でエラーになってしまいます。 use Encode; を使って、 from_to($txt, 'shiftjis', 'euc'); としてみましたが、 from_to($txt, 'shiftjis', 'euc'); のところでエラーになってしまいます。 ActivePerl-5.14ですと、どのように文字コードの変換をすればいいのでしょうか。 どなたか教えてください。 よろしくお願いいたします。

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

    こんにちは。いつもお世話になっております。 Encodeモジュールについて質問です。インプレスジャパンから出版 されている「まるごとPerl」にEncodeについて読みましたが、理解 できていないのか、いざスクリプトを書くとうまくいきません。 練習として記述し、utf-8で保存したのが下記です。 use strict; use warnings; use Encode; my $test='文字化けしやすい漢字です。表圭臀能'; my $moji=decode('utf-8',$test); my $ans=encode('utf-8',$moji); print "Content-type: text/html;charset=utf-8\n\n"; print <<EOH; <html> <head> <META http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Encode</title> </head> <body> <p class="moji">$ans</p> </body> </html> EOH そもそも、スクリプトをshift_jisで保存したときに文字化けが 起きないようにしたかったので、上記のスクリプトを変えて、 my $moji=decode('shift_jis',$test); my $ans=encode('utf-8',$moji);  そしてshift_jisで保存して実行してみましたが、ブラウザには 何も表示されません。 どこが間違っているのか、教えて頂ければ幸いです。 かなり初歩的な内容だと思いますが、どうぞよろしくお願い申し上げます。

    • ベストアンサー
    • Perl
  • 文字変換について

    Perlの文字変換について質問があります。 文字コードをJISからShift_JISに変換するには、下記のどれが正しい記述なのでしょうか? ・Encode::from_to($_, "jis", "shiftjis" ) ・encode("shiftjis", $_) ・encode("shiftjis", decode("utf8", $_)) 以上、よろしくお願い致します

    • ベストアンサー
    • Perl

専門家に質問してみよう