プロが教える店舗&オフィスのセキュリティ対策術

nagilumと申します。
「10日でおぼえるJSP/サーブレット 入門教室」という、2002年に発売された
ちょっと旧い本で勉強をしています。

下記はその中のJSPのコードで、クライアント(ウェブブラウザ)から受け取った
文字列をハッシュのキーとして検索して、値の内容を表示するものです。

ウェブブラウザから正しい(ハッシュに存在するキー)文字列を入力しても、
ハッシュのキーにヒットしません。
日本語の文字コードの問題のようですが、下記のコードをどのように修正すれば
よいのかわかりません。
すみません、助けてください。

クライアント(ウェブブラウザ)は Windows (Shift_JIS) です。
サーバ(Apache+Tomcat)は Fedora Core 4 (UTF-8) です。

よろしくお願いします。


1 <%@ page contentType="text/html;charset=UTF-8" import="java.util.*,java.io.*" %>
2 <%!
3 public String strEncode( String strVal ) throws UnsupportedEncodingException {
4 if( strVal == null ){ 5 return null;
6 }
7 else {
8 return new String( strVal.getBytes( "ISO-8859-1" ), "JISAutoDetect" );
9 }
10 }
11 %>
12 <html>
13 <head>
14 <title>アドレス帳検索(検索結果)</title>
15 </head>
16 <body>
17 <h1 style="background:#cccccc">アドレス帳検索</h1>
18 <%
19 HashMap hm = new HashMap();
20 hm.put( "輪笠貴子", "女, 0xx-xxx9-1111,横浜市まるばつ町5-18-199" );
21 hm.put( "佐々木健司", "男,04x-231x-xxxx,川崎市まるまる町1-3213" );
22 hm.put( "鳥内都", "女,09x-21xx-xx97,横浜市なになに区5-16" );
23 hm.put( "金崎瑞穂", "女,02x-654x-324x,相模原市なんとか区1-9-21" );
24 String strName = strEncode( request.getParameter( "name" ) );
25 if( hm.containsKey( strName ) ){
26 String strResult = (String)hm.get( strName );
27 StringTokenizer tkn = new StringTokenizer( strResult, "," );
28 %>
29 <dl>
30 <dt style="font-size:14pt;font-weight:bold">
31 <%= strName %>
32 </dt>
33 <dd>
34 <ol>
35 <li><%= tkn.nextToken() %></li>
36 <li><%= tkn.nextToken() %></li>
37 <li><%= tkn.nextToken() %></li>
38 </ol>
39 </dd>
40 </dl>
41 <%
42 }
43 else {
44 %>
45 <div style="color:Red">指定された名前は見つかりませんでした</div>
46 <%
47 }
48 %>
49 </body>
50 </html>

↑きちんと整形したコードをペーストしたのですが、
ブランクが全部削られてしまってとても読みにくくなってます。
ごめんなさい。

A 回答 (2件)

1.このソースをUTF-8で保存していること。


※例えばWindowsのメモ帳だとShift_JIS(Windows-31J)で保存されてしまいます。
2.Tomcatのconfフォルダ内にあるweb.xmlでJSPのjavaEncodingをUTF-8で指定していること。
※確かTomcatはデフォルトでUTF-8だった気がしますが、念のため
3.8行目の
>return new String( strVal.getBytes( "ISO-8859-1" ), "JISAutoDetect" );
ですが
JISAutoDetectの場合UTF-8は自動認識されなかったと思います。
基本的に自動にまかせるのではなくクライアントから送出される文字コードがわかっている場合は明示すべきです。
今回は"JISAutoDetect"を"UTF-8"に変えてみてください。

以上の条件を満たせば正しく動くかと思いますのでご確認頂ければと思います。
    • good
    • 0
この回答へのお礼

ARIA9様

助かりました! ちゃんと期待通りに動作するようになりました。

> 1.このソースをUTF-8で保存していること。
> ※例えばWindowsのメモ帳だとShift_JIS(Windows-31J)で保存されてしまいます。

これは自信ありです。
JSPのエディットは、Windows から Fedora へ SSH でログインして vi で行って
おります。

> 2.Tomcatのconfフォルダ内にあるweb.xmlでJSPのjavaEncodingをUTF-8で指定していること。
> ※確かTomcatはデフォルトでUTF-8だった気がしますが、念のため

確認しました。
コメント中に javaEncoding は [UTF-8] と書いてありまして、
これはきっと、デフォルトが UTF-8 ってことですよね、ARIA9さんが言及されて
いるとおり。
そして、xml本体中には javaEncoding を明示指定している箇所は存在しません。
よって、UTF-8 です。

> 3.8行目の
> >return new String( strVal.getBytes( "ISO-8859-1" ), "JISAutoDetect" );
> ですが
> JISAutoDetectの場合UTF-8は自動認識されなかったと思います。
> 基本的に自動にまかせるのではなくクライアントから送出される文字コードが
> わかっている場合は明示すべきです。
> 今回は"JISAutoDetect"を"UTF-8"に変えてみてください。

これが原因でした。
ARIA9さんのご指示通りに修正したところ、うまくいきました。
でも、狐につままれたような気分です。
自分の理解では、元々のコード中の "JISAutoDetect" は、
クライアント(Windows+IE)から送られてくる Shift_JIS(Windows31J)を自動認識
するための記述だと思っていました。つまり、上記の return 文では

  ISO-8859-1 でバイト列化したものは日本語かもしれないので
  自動認識せよ

という意味だと思っていたのです。
この return 文での "JISAutoDetect" を "UTF-8" に変更するとうまくいくという
ことは、正しい解釈は

  ISO-8859-1 でバイト列化したものを UTF-8 に変換せよ

ってことでしょうか?

我ながら浅い頭脳で恥ずかしいのですが、解説をお願いできませんでしょうか。

よろしくお願いします。

お礼日時:2007/04/11 08:07

nagilum様



No.1の回答をしたARIA9です。

ご質問の件回答致します。

>クライアント(Windows+IE)から送られてくる Shift_JIS(Windows31J)を自動認識
するための記述だと思っていました。

とありますが、クライアントから送られてくる文字コードは送り元ページのエンコーディング依存になります。
例えばグーグルをIEで開いて、IEの表示→エンコードを見るとUTF-8になっていると思います。
この場合にリクエストを発行すると送出されるデータはShift_JISではなくUTF-8になります。
掲載されていたソースで
>contentType="text/html;charset=UTF-8"
とありましたので恐らくリクエスト送出元のページがUTF-8であると見込みをたてて回答させて頂いていました。

>ISO-8859-1 でバイト列化したものは日本語かもしれないので
>自動認識せよ
>という意味だと思っていたのです。

こちらはその通りですが、JISAutoDetectはあくまで「きっとこれが正しいよ!」という
認識をするものですので必ず正しいコードを返す保障はありません。
システムで扱う文字コードに一意性を持たせて、明示的に文字コードを指定する方が良いでしょう。
参考URLでJDK1.6のJISAutoDetectについて掲載されていますのでご覧になってください。
ここを見るとUTF-8はJISAutoDetectで認識できないことがわかります。

>  ISO-8859-1 でバイト列化したものを UTF-8 に変換せよ
>ってことでしょうか?

その通りです。

ということで、今回はクライアントから送出されてくるリクエストデータが
UTF-8であったが、Windows-31Jと思っていたことが根本的な原因だったと思われます。

参考URL:http://java.sun.com/javase/ja/6/docs/ja/technote …
    • good
    • 0
この回答へのお礼

ARIA9様

お礼が遅くなりました。ごめんなさい。

丁寧に解説をいただき、本当にありがとうございます。
おかげさまで、得心がいきました。

> ということで、今回はクライアントから送出されてくるリクエストデータが
> UTF-8であったが、Windows-31Jと思っていたことが根本的な原因だったと思われます。

そのとおりですね。
件のJSPには encoding を指定していましたが、このJSPにジャンプする元の
HTMLには特定の encoding を指定していませんでした。
なので、きっとデフォルトの Windows-31J だろうと思いこんでしまっていました。

IEというか、世のウェブブラウザは自分が考えていたよりもずっと賢くできて
いるんですね。UTF-8で書かれたHTMLはちゃんとUTF-8として認識しているようです。
IEのポップアップメニューの「エンコード」を使って確認したところ、
ウェブサイトによってUTF-8だったりEUCだったり、自動的に識別していました。

重ねてお礼申し上げます。
ありがとうございました。

お礼日時:2007/04/14 10:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!