GBK,UTF-8,ISO 8859-1との符号化区別get,post要求中国語文字化けし処理

5432 ワード

1.コードの基礎知識


最初の符号化はiso 8859−1であり、ascii符号化と類似している.しかし,様々な言語を容易に表現するために,次第に多くの標準符号化が出現し,重要なのは以下のいくつかである. 

1.1. iso 8859-1は通常Latin-1と呼ばれています


最大で表示できる文字範囲は0-255で、英語シリーズに適用されます.例えば、アルファベットaの符号化は0 x 61=97である. 
明らかにiso 8859-1符号化表示の文字範囲は狭く、中国語文字を表すことができない.しかし、シングルバイト符号化であり、コンピュータの最も基本的な表示単位と一致するため、iso 8859-1符号化を用いて表示されることが多い.また、多くのプロトコルでは、デフォルトでこの符号化が使用されます.例えば、「中国語」の2文字にiso 8859-1符号化は存在しないが、gb 2312符号化を例にとると、「d 6 d 0 cec 4」の2文字(java文字が2バイトを占める)であるべきであり、iso 8859-1符号化を用いる場合は「d 6 d 0 ce c 4」(実際には、記憶を行う際にもバイト単位で処理される)と4バイトに分解して表す.一方、UTF符号化であれば、6バイト「e 4 b 8 ad e 6 96 87」である.この表現方法はまた別の符号化に基づいていることが明らかである. 

2.2. GB2312/GBK 


これが漢字の国標コードで、iso 8859-1符号化に特化しています.ここで、gbkはgb 2312符号化に互換性がある. 

1.3 unicode 


これは最も統一された符号化であり、すべての言語の文字を表すことができ、英字を含む定長2バイト(4バイトもある)符号化である.したがってiso 8859−1符号化にも符号化にも互換性がないと言える.ただし、iso 8859−1符号化に対してuniocode符号化は、アルファベットaが「00 61」であるなど、0バイト前に追加されただけである. 
なお、固定長符号化はコンピュータ処理に便利であり(GB 2312/GBKは固定長符号化ではないことに注意)、unicodeはすべての文字を表すために使用されるため、javaなどのunicode符号化を使用して多くのソフトウェア内部で処理される. 

1.4 UTF 


unicode符号化はiso 8859−1符号化に互換性がなく、より多くの空間を占有しやすいことを考慮すると、英語のアルファベットに対してunicodeも2バイトで表す必要があるためである.そのためunicodeは転送とストレージに不便です.従ってutf符号化が生成され、utf符号化はiso 8859−1符号化と互換性があり、同時にすべての言語の文字を表すためにも用いられるが、utf符号化は不定長符号化であり、各文字の長さは1〜6バイトから等しくない.またutf符号化には簡単な検証機能が付属している.一般的に、英語のアルファベットは1バイトで表され、漢字は3バイトで表される. 
注意、utfはより少ないスペースを使用するために使用されると言われていますが、それはunicode符号化に比べて漢字であることが分かっていれば、GB 2312/GBKを使用することが最も節約されるに違いありません.一方、utf符号化は漢字に対して3バイトを用いるが、漢字ページであってもunicode符号化よりもutf符号化が節約される.なぜなら、ページには多くの英語文字が含まれているからである. 

2.Unicode、UTF-8とISO 8859-1はいったいどんな違いがあるのか


「中国語」の2文字を例にとると、GB 2312の符号化は「d 6 d 0 cec 4」、Unicodeの符号化は「4 e 2 d 6587」、UTFの符号化は「e 4 b 8 ad e 69687」であることがわかる.なお、この2つの文字はiso 8859−1符号化されていないが、iso 8859−1符号化で表すことができる. 

3.java対文字の処理


Javaアプリケーションでは、文字セットの符号化に関連する箇所が多く、正確な設定が必要な箇所もあれば、ある程度の処理が必要な箇所もあります. 

3.1 getBytes(charset) 


これはjava文字列処理の標準関数であり、文字列で表される文字をcharsetで符号化し、バイトで表す役割を果たす.注意文字列はjavaメモリに常にunicode符号化されて格納されます.例えば「中国語」は、通常(すなわちエラーがない場合)は「4 e 2 d 6587」と記憶され、charsetが「gbk」であれば「d 6 d 0 cec 4」と符号化され、バイト「d 6 d 0 ce c 4」を返す.charsetが「utf 8」の場合、最後は「e 4 b 8 ad e 6 96 87」である.「iso 8859-1」の場合、符号化できないため、最後に「3 f 3 f」(2つの疑問符)を返す. 

3.2 new String(charset) 


これはjava文字列で処理されるもう一つの標準関数であり、前の関数とは逆にバイト配列をcharset符号化に従って組み合わせて識別し、最後にunicodeストレージに変換する.上記getBytesの例を参照すると、「gbk」も「utf 8」も正しい結果「4 e 2 d 6587」が得られるが、iso 8859-1は最後に「003 f 003 f」(2つの疑問符)になった.utf 8はすべての文字を表す/符号化するために使用できるので、new String(str.getBytes(「utf 8」)、「utf 8」)==str、すなわち完全に可逆的である. 

3.3 setCharacterEncoding() 


この関数はhttpリクエストまたは対応する符号化を設定するために使用されます. 
requestでは、コミットされたコンテンツの符号化を指し、指定後にgetParameter()で直接正しい文字列を得ることができ、指定しない場合はiso 8859-1符号化がデフォルトで使用され、さらなる処理が必要である.
下記「フォーム入力」を参照してください.なお、setCharacterEncoding()を実行するまでgetParameter()は実行できません.JAva docで説明:This method must be called prior to reading request parameters or reading input using getReader()また,この指定はPOSTメソッドにのみ有効であり,GETメソッドには無効である.解析理由は、POSTメソッドが最初のgetParameter()を実行するとjavaはすべてのコミット内容を符号化に従って解析し、後続のgetParameter()は解析しないのでsetCharacterEncoding()は無効です.GETメソッドのコミットフォームでは、コミットされたコンテンツがURLの中にあり、最初からすべてのコミットされたコンテンツをエンコード分析していたので、setCharacterEncoding()は自然に無効になります.
注意:iso-8859-1はJAVAネットワーク転送で使用する標準文字セットであり、gb 2312は標準中国語文字セットである.フォームの提出などネットワーク転送が必要な操作を行う場合は、iso-8859-1をgb 2312文字セット表示に変換する必要がある.そうしないと、ブラウザのgb 2312フォーマットでiso-8859-1文字セットを解釈すると、2者は互換性がないため、文字化けになる.
例:
String s = " ";
//  
byte[] utf = s.getBytes("utf-8");
byte[] gbk = s.getBytes("gbk");
System.out.println("utf-8 :" + Arrays.toString(utf));//[-28,-67,-96,-27,-91,-67]  6 System.out.println("gbk :" + Arrays.toString(gbk));//[-60,-29,-70,-61] 4 
//   
String s1 = new String(utf, "utf-8"); //  S
tring s2 = new String(utf, "gbk"); // gbk : ソ gbk 2 , 
String s3 = new String(gbk, "utf-8"); // gbk utf-8 :??? utf-8 6 
System.out.println("--------------------");
System.out.println("utf-8 :" + s1);
System.out.println("gbk :" + s2);
System.out.println("gbk utf-8 :" + s3);
System.out.println("---------------------");
System.out.println(" utf-8 ");
s3 = new String(s3.getBytes("utf-8"), "gbk"); //  ?   gbk utf-8 System.out.println(s3);

法則:


utf-8符号化はgbkとiso 8859-1で復号して戻すことができる
gbk符号化後iso 8859-1で復号して戻すしかない
 

GetとPostリクエストの中国語の文字化けしを解決する


Postリクエストでは、サーブレットまたはjspに次のコードを書き込むだけでフォームからの中国語の文字化けしを解決できます.
  request.setCharacterEncoding("utf-8");
Getリクエストでは、リクエストパラメータがアドレスバーのURLに添付された後になるので、上記の処理方法は使えません.次のようにする必要があります.
   String str=request.getQueryString();
//URLDecoderで文字列を復号する
   String str1=java.net.URLDecoder.decode(str,"utf-8");
   String[] paraStrings=str1.split("&");
//paraStrings[0]は最初のパラメータで、順番に類推します...
   for(String paraString : paraStrings)
{
     String[] nameValue=paraString.split("=");
//nameValue[0]はフォームのname、nameValue[1]はフォームのnameに対応する値です
}
もう1つの方法は、要求パラメータを取得した後、要求パラメータ値を再符号化することであり、すなわち、まずバイト配列に変換し、バイト配列を文字列に再復号することである.
  String str=request.getParameter("name");
  byte[] bytes=str.getBytes("ISO-8859-1");
  String name=new String(bytes,"utf-8");