みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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で保存して実行してみましたが、ブラウザには
何も表示されません。
どこが間違っているのか、教えて頂ければ幸いです。
かなり初歩的な内容だと思いますが、どうぞよろしくお願い申し上げます。

投稿日時 - 2007-06-18 15:21:14

QNo.3095122

困ってます

質問者が選んだベストアンサー

正直な話、「ShiftJISでスクリプトを書かない」
のが一番なんですけどね。

そうも言ってられない事情もあるでしょうから幾つか提案を。

1. use encoding 'shiftjis' (もしくは 'cp932')を指定する

このプラグマを指定することにより、スクリプトを
ShiftJISで記述しても、今回引っかかったような
ダメ文字問題にははまりません。

しかしながら、うまい話の裏には落とし穴があります。
・use encoding '...' した状態では正しく動かないモジュールが
少なからず存在する。
・自分の預かり知らないところで自動的に変換されるので、
変換する前の文字列が欲しくても手に入らないときがある。
・マルチスレッドにできない

In other words, do not C<use encoding> unless you are certain that the
program will not deal with any raw, 8-bit binary data at all.

というのは開発者の一人の弁です。

2. 文字列リテラルをスクリプトに直接書くのを止める

適当な別ファイルに書き出しておいて、
いちいちそれをロードする(必要なら変換もそこで行う)
ようにするわけです。

質問にあった
>ただ、フォームのようなクライアント側がキーボードで入力する
>場合は、\を追加するわけにいかないと思いますし

ですが、リテラルとしてスクリプトに書かなければ
追加するようなことをしないでも問題ないです。
""とか''などで示された文字列を解釈するときの問題であって、
文字列として入力されたものをどう扱うかの問題ではないからです。

いずれにしろjperlはもうリリースされることはありませんから、
shitjisを透過に何の問題もなく使えるという期待は
しないほうが良いです。

投稿日時 - 2007-06-18 18:15:35

お礼

sakusaker7様
回答ありがとうございました。use encoding 'shift_jis';は
危険なのですね。勉強になりました。
ヘッダに
print "Content-type: text/html; charset=shift_jis\n";
と記述したこともあります。
文字化けは、しなかったのですが自分が試したかったのはutf-8に
符号化することだったので他の方法を探していました。
フォームを含むhtmlファイルとスクリプトの両方をutf-8で保存
し、charsetの宣言もしたら、問題なく表示されましたので、
やはりおっしゃる通り、ShiftJISでスクリプトを書かないというのが
一番なのですね。
回り道をしながら、かなりの時間をかけて試してみましたが
少しずつ前進してきました。
初心者の質問に丁寧に答えてくださり、本当にありがとうございました。

投稿日時 - 2007-06-18 21:19:35

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

よ~するに「スクリプトで使うエンコーディングを指定」すればいいんだけど....
手を抜くなら encoding プラグマかなぁ?

投稿日時 - 2007-06-18 18:00:26

ANo.1

スクリプトをいきなりCGIとして動かしていたりしていませんか?
サーバーにアップロードして動かす前に、
シェルで動かしてみましょう。

> my $moji=decode('shiftjis',$test);

この行にエラーがあるという報告が出ているはずです。
が、実際には原因はそこではないのですが。

問題は
>my $test='文字化けしやすい漢字です。表圭臀能';

shiftjisで記述した場合、'能'の第二バイトは
'\' と同じですので、
上の行の文字列の代入は'能'までで終わらず
さらに先までみていくことになります。

そして、decodeの引数の'shiftjis'の
開きのクォートを見つけたところで文字列が終わったと見なしますが、
さらに見ていったときに登場するshitjis
を解釈できないのでエラーになる
というわけです。

エラーが発生したためHTMLデータを作成することができなかったので
ブラウザから見ても何もないという結果になったわけです。

とりあえずは
> my $test='文字化けしやすい漢字です。表圭臀能\';

能の後ろに'\'をつければ回避できます。

その他の指摘事項はとりあえず出さないでおきます。

投稿日時 - 2007-06-18 15:42:18

お礼

sakusaker7様
こんにちは。早速の回答ありがとうございます。
サーバにはアップロードしておりませんが、環境について書くのを
忘れておりました。申し訳ありません。
WindowsXPにAN HTTPD Daemonをインストールして、ローカルで検証しています。
文字に関することなのでブラウザで確認していました。
コマンドプロンプトで実行すると、
Bad name after shift_jis' at moji3.cgi line 7. と表示されます。
回答を拝見して、能の2バイト目について(5C)よく分かりました。
\を入力すると確かに回避できましたし、最後の文字によって\が不要
なこともありますね。
ただ、フォームのようなクライアント側がキーボードで入力する
場合は、\を追加するわけにいかないと思いますし、Encodeモジュールは、文字化けを一気に解決してくれるのかと多大な期待を持って
本を読んでいたところです。
\を付ける以外、どんな解決策がありますでしょうか?
お忙しいところ申し訳ありませんが、よろしくお願い申し上げます。

投稿日時 - 2007-06-18 17:27:39

あなたにオススメの質問