Java 中文字符串編碼之GBK轉UTF-8


寫過兩篇關於編碼的文章了,以為自己比較了解編碼了呢?!

結果今天又結結實實的上了一課。

以前轉來轉去解決的問題終歸還是簡單的情形。即iso-8859-1轉utf-8,或者iso-8859-1轉gbk,gb2312之類。這種無損轉換,一行代碼就搞定。

今天遇到了gbk轉utf-8。無論怎么轉,都是亂碼。

一、亂碼的原因

gbk的中文編碼是一個漢字用【2】個字節表示,例如漢字“內部”的gbk編碼16進制的顯示為c4 da b2 bf

utf-8的中文編碼是一個漢字用【3】個字節表示,例如漢字“內部”的utf-8編碼16進制的顯示為e5 86 85 e9 83 a8

很顯然,gbk是無法直接轉換成utf-8,少字節變為多字節,誰知道缺少的字節是什么啊?!

二、轉換的辦法

有辦法實現“有損”轉換嗎?答案是肯定的。

1.首先將gbk字符串getBytes()得到兩個原始字節,轉換成二進制字符流,共16位。

2.根據UTF-8的漢字編碼規則,首字節以1110開頭,次字節以10開頭,第3字節以10開頭。在原始的2進制字符串中插入標志位。最終的長度從16--->16+4+2+2=24。

3.轉換完成,實際情況需要考慮更多因素,例如字符串是漢字和數字的混合體,需要識別處理數字。

三、不要重復發明輪子

這段代碼測試可用還很好用,需要的可以參考。

 1 public static String getUTF8StringFromGBKString(String gbkStr) {  
 2         try {  
 3             return new String(getUTF8BytesFromGBKString(gbkStr), "UTF-8");  
 4         } catch (UnsupportedEncodingException e) {  
 5             throw new InternalError();  
 6         }  
 7     }  
 8       
 9     public static byte[] getUTF8BytesFromGBKString(String gbkStr) {  
10         int n = gbkStr.length();  
11         byte[] utfBytes = new byte[3 * n];  
12         int k = 0;  
13         for (int i = 0; i < n; i++) {  
14             int m = gbkStr.charAt(i);  
15             if (m < 128 && m >= 0) {  
16                 utfBytes[k++] = (byte) m;  
17                 continue;  
18             }  
19             utfBytes[k++] = (byte) (0xe0 | (m >> 12));  
20             utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));  
21             utfBytes[k++] = (byte) (0x80 | (m & 0x3f));  
22         }  
23         if (k < utfBytes.length) {  
24             byte[] tmp = new byte[k];  
25             System.arraycopy(utfBytes, 0, tmp, 0, k);  
26             return tmp;  
27         }  
28         return utfBytes;  
29     }  

PS:有點兒對不住原作者,找了很多代碼,一一測試,結果網頁都關閉了,如果有大神認領,我一定補充鏈接,而且深表感謝。


免責聲明!

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



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