2012年5月7日月曜日

Servletの日本語コードの問題

バイトデータをStringオブジェクトに変換するためには、正しい「日本語エンコード」を指定する必要があります。つまり、1バイト文字なのか、2バイト文字なのか、また2バイトからなる漢字をどのように変換するのかを指定して変換しなければなりません。
Javaではこのような変換は基本的に水面下で行なわれますが、このとき使われるのは「デフォルトの」日本語エンコードです。WindowsなどではShift-JISと呼ばれるものが利用されたりします。
Tomcatは、受け付けたパラメータのバイトデータをStringオブジェクトに変換してgetParameter(String)メソッドで参照可能にするわけですが、この変換に問題があるために、今までの例では日本語を入力すると「????」などとなってしまっていました。

この問題を回避するためには、一度Tomcatによって変換されてしまったStringオブジェクトをバイトデータに戻し、再び正しい日本語エンコードでStringオブジェクトに変換するという手続きが必要になります。
この手続きは、Javaでは以下のように記述します。

        String target = request.getParameter( "sample-param" );
        
        // String -> bytes
        byte[] rawbytes = target.getBytes( "8859_1" );
        // bytes -> String
        String jatarget = new String( rawbytes, "JISAutoDetect" );
        

または、もっと短く、

        String target = request.getParameter( "sample-param" );
        
        // 1行で変換
        String jatarget = new String( target.getBytes( "8859_1" ), "JISAutoDetect" );
        

このようにすると「????」ではなく、きちんと日本語が表示されるようになります。

サンプルコード

実際のコーディング例を示します。 これまでの例に、日本語変換のコードを追加したものです。
コンパイル方法、form.html、web.xmlの内容、warファイルの作成方法は前の章とまったく同じです。

FormServlet.java
0:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
 import javax.servlet.*;
 import javax.servlet.http.*;
 import java.io.*;
 
 public class FormServlet extends HttpServlet {
 
    public FormServlet() {
      super();
    }
 
    protected void doPost( HttpServletRequest request, HttpServletResponse response )
      throws ServletException, IOException {
 
      response.setContentType( "text/html;charset=Shift_JIS" );
      PrintWriter out = response.getWriter();
      
      // パラメータの取得
      String name = request.getParameter( "name" );
      String address = request.getParameter( "address" );
      String message = request.getParameter( "message" );
      
      // 日本語を修正
      String janame = new String( name.getBytes( "8859_1" ), "JISAutoDetect" );
      String jaaddress = new String( address.getBytes( "8859_1" ), "JISAutoDetect" );
      String jamessage = new String( message.getBytes( "8859_1" ), "JISAutoDetect" );
 
      out.println( "<html>" );
      out.println( "<body>" );
      out.println( "<h1>フォームデータの取得</h1>" );
      out.println( "<h2>そのままだと</h2>" );
      out.println( "<dl>" );
      out.println( " <dt>name</dt>" );
      out.println( " <dd>" + name + "</dd>" );
      out.println( " <dt>address</dt>" );
      out.println( " <dd>" + address + "</dd>" );
      out.println( " <dt>message</dt>" );
      out.println( " <dd>" + message + "</dd>" );
      out.println( "</dl>" );
      out.println( "<h2>日本語問題を修正</h2>" );
      out.println( "<dl>" );
      out.println( " <dt>name</dt>" );
      out.println( " <dd>" + janame + "</dd>" );
      out.println( " <dt>address</dt>" );
      out.println( " <dd>" + jaaddress + "</dd>" );
      out.println( " <dt>message</dt>" );
      out.println( " <dd>" + jamessage + "</dd>" );
      out.println( "</dl>" );
      out.println( "</body>" );
      out.println( "</html>" );
 
    }

0 件のコメント:

コメントを投稿