轉載自:https://www.cnblogs.com/yoyotl/p/5979200.htmlphp
1、亂碼的緣由html
gbk的中文編碼是一個漢字用【2】個字節表示,例如漢字「內部」的gbk編碼16進制的顯示爲c4 da b2 bf編碼
utf-8的中文編碼是一個漢字用【3】個字節表示,例如漢字「內部」的utf-8編碼16進制的顯示爲e5 86 85 e9 83 a8code
很顯然,gbk是沒法直接轉換成utf-8,少字節變爲多字節,誰知道缺乏的字節是什麼啊?!htm
有辦法實現「有損」轉換嗎?答案是確定的。blog
1.首先將gbk字符串getBytes()獲得兩個原始字節,轉換成二進制字符流,共16位。utf-8
2.根據UTF-8的漢字編碼規則,首字節以1110開頭,次字節以10開頭,第3字節以10開頭。在原始的2進制字符串中插入標誌位。最終的長度從16--->16+4+2+2=24。字符串
3.轉換完成,實際狀況須要考慮更多因素,例如字符串是漢字和數字的混合體,須要識別處理數字。get
public void entityTest(){
try {
byte[] str = "支持™".getBytes("gbk");
String gbkStr = new String(str, "gbk");
System.out.println(new String(getUTF8BytesFromGBKString(gbkStr),"UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
int n = gbkStr.length();
byte[] utfBytes = new byte[3 * n];
int k = 0;
for (int i = 0; i < n; i++) {
int m = gbkStr.charAt(i);
if (m < 128 && m >= 0) {
utfBytes[k++] = (byte) m;
continue;
}
utfBytes[k++] = (byte) (0xe0 | (m >> 12));
utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
}
if (k < utfBytes.length) {
byte[] tmp = new byte[k];
System.arraycopy(utfBytes, 0, tmp, 0, k);
return tmp;
}
return utfBytes;
}
但在這裏仍是有個問題是"支持™"字符串中"™"的字符因爲在GBK中不存在,那麼在byte[] str = "支持™".getBytes("gbk");的時候"™"字符就已經亂碼了,最後致使轉碼也亂碼。GBK還有不少不支持的特殊字符。it