【轉】【編碼】偶數個漢字正常,奇數個漢字亂碼


原文:http://www.cnblogs.com/bfchuan/p/4083548.html

原文中提到:“我很好“出現的亂碼情況。

一般在漢字亂碼中分為兩種情況:

  1:騫茶帿瀛�  這樣的亂碼其實不叫亂碼,而是數據不是我們想要的,因為我們要的是A卻顯示成了B,這樣的原因主要是因為編碼格式不正確導致

  2:?????  全是問號的亂碼應該很多人都遇見過,這樣的東西應該才是算亂碼,為什么會出現?。因為字節內的東西無法用一個漢字展示出來,也就是找不到漢字對應這個內容,於是這樣的東西會以?的形式展示出來,官方的稱呼就是編碼黑洞,對應的二進制數據為63,轉換后就是一個?

 

  根據情況來看自己遇到的是第一種,於是有點疑惑,管他的,來個強轉:

  

復制代碼
   ChangeCharset changeCharset = new ChangeCharset();
        try {
            result = changeCharset.toUTF_8(URLDecoder.decode(result, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
復制代碼

 

機器人說:你好愛你哦親??

  有部分亂碼,於是繼續測試想找出規律,后來果然發現規律,只要過來的數據是偶數個,則不會亂碼,若是奇數個,則最后一個漢字亂碼,亂碼的形式是固定的?,來了一個?,我靠,今天兩種情況都遇到了,本以為很簡單的東西居然卡在了編碼的地方,苦思冥想,很明顯是容器編碼問題,很SB的解決方法也很簡單,判斷下是不是奇偶,不是偶數加個東西就行了。

 

  但是想搞明白為什么是最后一個字亂碼,突然想到一個東西,UTF-8中,一個漢字3個字節,GBK中一個漢字2個字節,我好像明白了什么。。

 

  因為jetty容器默認是按照系統編碼來決定容器編碼,前提是沒有自己修改啟動編碼,而公司里我台PC是windows的,好像默認GBK的,反正我對windows緋聞也挺多的,於是這里有一個問題,比如jetty接受到了一串經過UTF-8編碼的漢字:

  我很好

  jetty收到的最原始的二進制數組是這樣的:

  [-26, -120, -111, -27, -66, -120, -27, -91, -67]

  當然這不是最原始的,最原始的0和1,當然為了好看就算他是最原始的吧,下一步jetty要開始編碼了,按照jetty的GBK編碼,他按照2個字節一個漢字的格式去編碼,於是出現了這樣的組合:

  [-26, -120]  [ -111, -27]  [-66, -120]  [-27, -91]  [-67]

  前面每兩個字節都能找到對應的漢字,最后jetty發現最后居然只有一個字節,找不到對應的漢字,心里想這SB是哪來的,於是jetty放棄它了,把它趕出去,把63丟過去,於是最后的組合成了:

  [-26, -120]  [ -111, -27]  [-66, -120]  [-27, -91]  [63]

  經過GBK的格式編碼,兩個字節對應一個漢字,就顯示出了這樣的東西:

  騫茶帿瀛

  會出現5個,因為每2個字節代表一個漢字,最后一個字節是63,對應的符號是?,就出現了上面的東西,於是我對它做了強制的UTF-8編碼,導致上面的二進制數組重新組合,經過UTF-8的組合之后,二進制數組成了這樣:

  [-26, -120, -111] [-27, -66, -120] [-27, -91, 63]

  再經過UTF-8顯示之后,變成了這樣:

  我很�?

  前6個字節能夠正常的顯示出漢字,因為那就是真正的數據,然而最后3個字節,已經被GBK處理了,替換過了,即使使用UTF-8也無法還原它原來的容貌,於是它就顯示成了上面的樣子,但是為什么偶數不會出錯?

  因為偶數能夠被GBK正常的解碼,也就是如果漢字是偶數,UTF-8和GBK是等同的,但是如果是奇數,則就出問題了,這也是傳說中的最后一個漢字亂碼的問題,因為最后一個 字節始終是63,要解決這個問題,必須要治標還要治本,項目中必須全程保證編碼一致性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM