2013年1月20日日曜日

Webのgetメソッドで文字コード取得方法

ブラウザのURLから「http://localhost:8080/Yawdba1.0/Test?a=漢字」などと入力した指示を、サーブレットで処理する場合、パラメータaの値を解析する場合、上のように日本語文字が含まれていると、処理する文字コードが、ブラウザ毎にshiftJISだったり、unicodeだったりして文字化けが発生します。くわしくは、私のブログの以下をご覧下さい。Servletでのパラメータ解析(1)Servletでのパラメータ解析(2)Servletでのパラメータ解析(3)
これは、WebブラウザはURLに日本語文字コードを含む場合、URLエンコーディング(%xx形式)を施してWebサーバに送信します。このときのエンコーディング形式がshiftJISだったりunicodeだったりすることから、javaプログラムでは、以下の文字コード変換をしないと適切にパラメータを取得することはできません。
 
しかし、HTML formからのgetメソッド発行と異なり、直接ブラウザのURLから指定した場合には、各ブラウザ種別毎にの文字コードが異なります。例えば、OperaではJISコード、chromeでは、UTF-8, firefoxでは、shiftJISになっていたりします。

通常は、次のようなjavaプログラムで対応することが一般的かと思います。

     String p = req.getParameter("a");
  String v = new String(p.getBytes("iso-8859-1"),"JISAutoDetect");

これは、パラメータaの値が格納されているjavaの文字列変数であるname、自動的に文字コード(shiftJISやunicode)を判断して、java文字列に変換するものです。しかし、一体どの文字コードで変換されているか完全に判断することは不可能です。
そこで、ブラウザによらず文字コードを自動的に判断する方法を考えました。

この方法は、自動的に文字コードを判断するために、文字コードを判断するためのパラメータをgetメソッドに追加しました。例えば、

    http://localhost:8080/Yawdba1.0/Test?cs=あ&a=漢字

 のようにします。サーブレットサイドでは、getParametercでcsと言うパラメータの値を調査します。そのパラメータの値は、日本語の「あ」と取り決めておき、その値が実際どのコード体系で表現できるか判断することで、入力された文字コード体系の判別が可能となります。
ちなみ、Yawdba1.0では、以下コードで判別しています。

  String  value =  req.getParameter("cs");
  String  v     = "";

  /* value文字列内の%xx文字列を1バイト文字に変換する */
  for(int i=0; i < value.length();) {
    char ch1, ch2;
    if(value.charAt(i) == '%' &&

       i+2 < value.length()) {
      ch1 = value.charAt(i+1);
      ch2 = value.charAt(i+2);       

     v += (ch1 <='9'?(ch1-'0'):(ch1-'A'+10))*16 +
       (ch2 <='9'?(ch2-'0'):(ch2-'A'+10));
      i += 3;
    }
    else {
      v += value.charAt(i);
      i++;
    }
  }
  if(v.equals("\202\240"))     /* 82 A0 */
    char_set = "shiftjis";    // シフトJIS 
  else if(v.equals("\343\201\202"))  /* E3 81 82 */
    char_set = "utf8";         // UTF-8
  else if(v.equals("\244\242"))/* A4 A2 */
    char_set = "euc" ;         // EUC
  else if(v.equals("\033\044\102\044\042\033\050\102"))
                               /* $B  24 22 (B */
    char_set = Code.jis;       //JISコード


あとは、判別した文字コードにしたがって、
    String v = new String(p.getBytes("iso-8859-1"),"Windows-31J");
のように文字コード変換します。
 
 

0 件のコメント:

コメントを投稿