符号化、復号化、乱符号化、トランスコードの理解.


コンピュータにとって、どの数字もバイナリであり、文字も16進数(実はバイナリ)で表す、例えば「中国語」であり、通常(すなわちエラーがない場合)は「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つの疑問符)を返す.したがって、ここでは、我々が見たすべての文字ではなく、「ABCDEFG」のように復号することができ、「utf-8」に復号することができ、「GBK」、さらには「ASCII」であってもよいが、「hex」であってはならない.「HEX」は「G」という符号化フォーマットをサポートしていないからである.
つまり、異なる符号化フォーマットでは、文字の最下位は異なりますが、文字を正常に表示することはテーブルを調べる過程であり、ネットワーク、web、DBからデータを受け取ると、01バイナリ(最下位)の列に違いありません.そして、「テーブル」を探して、これらのバイナリ列を翻訳しなければなりません.このテーブルは文字符号化です.もしserverが私にgbkの01シーケンスをくれたら、私たちはutf-8の01シーケンスで翻訳をして、もちろん文字化けします.だから文字化けしの根本的な原因は私达が1枚の适切な“翻訳表”を探し当てて相手の私达の言语を翻訳することができませんでした.
Javaの文字列stringの符号化方法についてお話ししましょう.String.getByte(“”); この関数は復号関数であり、つまり、元の文字がどの符号化方式でサポートされているか、私たちは符号化プロセスに従って復号することができ、この関数はバイト配列、すなわちバイナリのシーケンスを返す.例:
   String str = " ";
        try {
            byte[] bytes = str.getBytes("gbk");
            byte[] bytes2=str.getBytes("utf-8");
            byte[] byte3=str.getBytes("ascii");// 
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

2.new String(byte[],“charset”)java文字列処理のもう一つの標準関数であり、前の関数とは逆にバイト配列をcharset符号化に従って組み合わせて識別し、最後にunicodeストレージに変換する.上記getBytesの例を参照すると、「gbk」と「utf 8」はいずれも正しい結果「4 e 2 d 6587」を得ることができるが、iso 8859-1は最後に「003 f 003 f」(2つの疑問符)になった.この関数の使用例は次のとおりです.
             try {  
                   String s=" ";
                   byte []b=s.getBytes("utf-8");  
                    String str=new String(b,"utf-8");
                    String str1=new String(b,"gbk");  
                    System.out.println(str);
                    System.out.println(str1);  
                } catch (UnsupportedEncodingException e) {  
                    e.printStackTrace();  
                }  

上のプログラムを実行すると、strが印刷されたのは正しいことがわかります.str 1が印刷されたのは、文字化けしています.
つまり、元は何の符号化方式だったのか、元の復号方式から符号化するのが正しい!実は、文字化けの原理を考えてみると、javaのIOストリームにInputStreamReader(InputStreamin,Charset cs)があり、トランスコードの橋であるという論理かもしれませんが、実は彼は何をしていますか.上のコードの中でやったことです!例えば、ネットワークで送信される文字がutf-8であれば、そのパラメータは「utf-8」に書き込まれ、同様に、サーバが「gbk」であれば「gbk」と書き、私たちはよくこのように使用します.(実はこのクラスは主にトランスコード操作を担当しています.トランスコードのためです).

              BufferedReader m_bufferedreader=new BufferedReader(new InputStreamReader(m_inputstream,encode));  
StringBuffer m_stringbuffer=new StringBuffer();  
 while((one_line_string=m_bufferedreader.readLine())!=null){  
                  m_stringbuffer.append(one_line_string);// String  

このように,文字ストリームを用いてストリームをキャッシュしてネットワークに読み込んだ文字を,stirngBuffererを用いてキャッシュすることは効率的である.それから私は今回のプロジェクトの中で出会った1つの问题を言います:私は1つのネットディスクのクライアントを书いて、サーバーから送られてきたHTTPの报文の中の报文の头のファイルを得なければならなくて、だから私は报文の中からファイルの名前を得て、英语は返して、中国语はほほほになって、また文字化を乱して、私はバックグラウンドの人と疎通して、结果は正しいことを発见して、无言で、それから长い间探してやっと见ました.HTTPメッセージの問題:HTTPメッセージの符号化フォーマットはISO-8895-1しかなく、他のものではないので、HTTPサーバーはメッセージを送信する時、元の符号化フォーマットを先にISO-8895-1に変換したのはこのような形式である:
      String s=" ";  
  try {  
    byte []b=s.getBytes("utf-8");  
    String str=new String(b,"iso-8895-1");  
    System.out.println(str);  
   catch (UnsupportedEncodingException e) {  
e.printStackTrace();  

だから、あなたがserverの符号化フォーマットutf-8と言っても、私の側もutf-8で解析したのではないでしょうか.役に立たないです.あなたが手に入れたのは文字化けしたもので、このように解決するのが正しいです.
byte []b=filename.getBytes("ISO-8859-1");  
filename=new String(b,"utf-8");  

この例は理解しにくいかもしれませんが、私は例えをして、サーバーは、まず1つの文字列(元のものがutf-8の符号化フォーマットであると仮定します)を、それからサーバーはこの文字列をutf-8の標準に従って、バイナリの文字列に復号して、それからISO-8859-1の符号化を行って、クライアントに送信します(しかし、どんなバイナリになっても、元の文字列が正しく表示されたいのは、utf-8を通過するしかありません)、だから、クライアントは、取得する文字列をISO-8859-1に従って元のutf-8のバイナリに復号し、utf-8に再結合する必要がある.正しく表示できる
これがこの問題の所在で、私はネット上でめったに解答がないのを見て、やはりみんなに話しましょう.主にHTTPのメッセージヘッダの制限符号化の問題である.符号化は常に比較的基礎的な問題であり、ネットワーク、暗号化復号、データベース操作にかかわらず、重視してください.