關於Tomcat中亂碼的產生原因詳解
阿新 • • 發佈:2019-02-09
getBytes() 與 getBytes(String charset)
無參表示當前平臺預設字符集
該方法的作用即,拿著你給的字串,去指定的碼錶中查詢其對應的位元組陣列
對於在碼錶中查詢不到的,統一給你個?
這個?對應位元組63,你會經常看到的
System.out.println(Arrays.toString(s.getBytes("iso-8859-1")));//[63, 63]
西歐碼錶中根本沒有中文,你拿這兩個字去找,肯定給你兩個問號啊
----------------------------------------------------------------------------
資料儲存的過程:
比如將“中國”存入Tomcat伺服器中
第一步,對中國呼叫getBytes()方法,假如是utf-8格式對應
[-28, -72, -83, -27, -101, -67],假如是gbk格式,對應的是[-42, -48, -71, -6]
第二步,拿著這個位元組陣列去西歐碼錶ISO8859-1中按它的規則查詢對應的字元
分別對應 ä¸å½ 和 Öйú
第三步,將查到的字元存起來(前後過程對應的位元組陣列是沒有變化)
上述過程的程式碼表現形式即:
String s1 ="中國";
String s2 = new String(s1.getBytes(),"iso8859-1");
資料取出的過程:
不做任何處理,必出亂碼,其程式碼表現形式
String s3 =
new String(s2.getBytes("iso8859-1"),"iso8859-1");
正確處理方式
String s3 = new String(s2.getBytes("iso8859-1"),"utf-8")
再次得到“中國”
---------------------------------------------------------------------------
以上述原理解釋,為什麼gbk轉不回utf8
String s1 ="中國";
String s2 = new String(s1.getBytes(),"utf-8");
System.out.println(s2); // ?й?
它在這一步就出了問題,也就是說拿著 [-28, -72, -83, -27, -101, -67]去GBK碼錶中找對應字元的時候,它連這個對應的字元都找不到,比如說-28,-72這兩個位元組不對應任何一個字元,這時候,它就扔了個問號?過來。這個過程中,對位元組陣列的內容產生了改變,再想通過這個機制轉回來是不可能實現的了
----------------------------------------------------------------------------
編碼:將看得懂的變成看不懂的
解碼:將看不懂的變成看得懂的
亂碼出現的原因:編碼方式與解碼方式不一致
我們當前系統預設編碼方式為gbk
String 類支援在建立時 按照指定編碼方式建立String物件,
如public byte[]
getBytes()
public byte[]
getBytes(String charsetname)
使用平臺的預設字符集或指定字符集將此 String 編碼為 byte 序列,並將結果儲存到一個新的 byte 陣列中
也可以將其他基本型別以指定的編碼格式進行解碼
如String(byte[] bytes,Charset charset)
通過使用指定的
charset 解碼指定的 byte 陣列,構造一個新的 String
------------------------------------------------------------------------------------------
getBytes()方法不存在正確錯誤的概念,重新編碼而已,與被編碼物件是什麼原編碼方式無關。只要保證解碼過程對應正確就不會亂碼
------------------------------------------------------------------------------------------
錯誤的編解碼方式
String s1 = "你好"; //當前的eclipse平臺預設編碼方式為gbk時
String s2 = new String(s1.getBytes("utf8"),"gbk");
System.out.println(s2); //浣犲ソ
System.out.println(Arrays.toString(s2.getBytes("gbk")));//[-28, -67, -96, -27, -91, -67]
String correctS2 = new String(s2.getBytes("gbk"),"utf8");
System.out.println(correctS2); //你好
String s3 = new String(s1.getBytes("gbk"),"utf-8");
System.out.println(s3);//???
System.out.println(Arrays.toString(s3.getBytes("gbk"))); //[63, 63, 63]
System.out.println(Arrays.toString(s3.getBytes("utf8")));//[-17, -65, -67, -17, -65, -67, -17, -65, -67]
String correctS3 = new String(s3.getBytes("utf8"),"gbk");
System.out.println(correctS3); //錕斤拷錕?
//s2能正確轉換是因為轉換過程中,位元組陣列對應的值沒有變化,2個漢字6個位元組的utf8編碼能找到對應的3個漢字6位元組gbk編碼
//s3在轉換過程中,位元組陣列發生了變化,2個漢字4個位元組的gbk編碼無法找到對應的utf-8對應的漢字,找來了不對應的一些奇怪的東西,此時無論怎麼轉都轉不回去了
-------------------------------------------------------------------------------------------------------