這兩天抽時間又總結/整理了一下各類編碼的實際編碼方式,和在Java應用中的使用狀況,在這裏記錄下來以便往後參考。
爲了構成一個完整的對文字編碼的認識和深刻把握,以便處理在Java開發過程當中遇到的各類問題,特別是亂碼問題,我以爲組成一個系列來描述和分析更好一些,包括三篇文章:
第一篇:JAVA字符編碼系列一:Unicode,GBK,GB2312,UTF-8概念基礎
第二篇:JAVA字符編碼系列二:Unicode,ISO-8859,GBK,UTF-8編碼及相互轉換
第三篇:JAVA字符編碼系列三:Java應用中的編碼問題
第二篇:JAVA字符編碼系列二:Unicode,ISO-8859-1,GBK,UTF-8編碼及相互轉換
1、函數介紹
在Java中,字符串用統一的Unicode編碼,每一個字符佔用兩個字節,與編碼有關的兩個主要函數爲:
1)將字符串用指定的編碼集合解析成字節數組,完成Unicode-〉charsetName轉換
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException
2)將字節數組以指定的編碼集合構形成字符串,完成charsetName-〉Unicode轉換
public String(byte[] bytes, String charsetName) throws UnsupportedEncodingException
2、Unicode與各編碼之間的直接轉換
下面以對中文字符串"a中文"的編碼轉換爲例,來了解各類編碼之間的轉換
1)Unicode和GBK
測試結果以下,每一個漢字轉換爲兩個字節,且是可逆的,即經過字節能夠轉換回字符串
String-GBK〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4
ByteArray-GBK〉String:0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u4E2D\u6587(a中文)
2)Unicode和UTF-8
測試結果以下,每一個漢字轉換爲三個字節,且是可逆的,即經過字節能夠轉換回字符串
String-UTF-8〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87
ByteArray-UTF-8〉String:0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉\u0061\u4E2D\u6587(a中文)
3)Unicode和ISO-8859-1
測試結果以下,當存在漢字時轉換失敗,非可逆,即經過字節不能再轉換回字符串
String-ISO-8859-1〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x61 0x3F 0x3F
ByteArray-ISO-8859-1〉String:0x61 0x3F 0x3F-〉\u0061\u003F\u003F(a??)
3、Unicode與各編碼之間的交叉轉換
在上面直接轉換中,由字符串(Unicode)生成的字節數組,在構造回字符串時,使用的是正確的編碼集合,若是使用的不是正確的編碼集合會怎樣呢?會正確構造嗎?若是不能正確構造能有辦法恢復嗎?會信息丟失嗎?
下面咱們就來看看這種狀況,這部分能夠說明在某些狀況下雖然咱們最終正確顯示告終果,但其間仍然進行了不正確的轉換。
1)可以正確顯示的中間不正確轉換
咱們知道String-GBK〉ByteArray-GBK〉String是正確的,但若是咱們採用String-GBK〉ByteArray-ISO-8859-1〉String呢?經過測試結果以下:
String-GBK〉ByteArray-ISO-8859-1〉String:\u0061\u4E2D\u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u00D6\u00D0\u00CE\u00C4(a????)
這時咱們獲得的字符串爲?亂碼「a????」,可是經過繼續轉換咱們仍然能夠復原回正確的字符串「a中文」,過程以下:
String-GBK〉ByteArray-ISO-8859-1〉String-ISO-8859-1〉ByteArray-GBK〉String
對應:\u0061\u4E2D\u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u00D6\u00D0\u00CE\u00C4(a????)-〉0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u4E2D\u6587(a中文)
也就是咱們在首次構造字符串時,咱們用了錯誤的編碼集合獲得了錯誤的亂碼,可是咱們經過錯上加錯,再用錯誤的編碼集合獲取字節數組,而後再用正確的編碼集合構造,就又恢復了正確的字符串。這時就屬因而「可以正確顯示的中間不正確轉換」。在Jsp頁面提交數據處理時經常發生這種狀況。
此外可以正確顯示的中間不正確轉換還有:
String-UTF-8〉ByteArray-ISO-8859-1〉String-ISO-8859-1〉ByteArray-UTF-8〉String
和
String-UTF-8〉ByteArray-GBK〉String-GBK〉ByteArray-UTF-8〉String
對應:\u0061\u4E2D\u6587(a中文)-〉0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉\u0061\u6D93\uE15F\u6783(a涓枃)-〉0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉\u0061\u4E2D\u6587(a中文)
4、編碼過程當中錯誤診斷參考
1)一個漢字對應一個問號
在經過ISO-8859-1從字符串獲取字節數組時,因爲一個Unicode轉換成一個byte,當遇到不認識的Unicode時,轉換爲0x3F,這樣不管用哪一種編碼構造時都會產生一個?亂碼。
2)一個漢字對應兩個問號
在經過GBK從字符串獲取字節數組時,因爲一個Unicode轉換成兩個byte,若是此時用ISO-8859-1或用UTF-8構造字符串就會出現兩個問號。
如果經過ISO-8859-1構造能夠再經過上面所說的錯上加錯恢復(即再經過從ISO-8859-1解析,用GBK構造);
如果經過UTF-8構造則會產生Unicode字符"\uFFFD",不能恢復,若再經過String-UTF-8〉ByteArray-GBK〉String,則會出現雜碼,如a錕斤拷錕斤拷
3)一個漢字對應三個問號
在經過UTF-8從字符串獲取字節數組時,因爲一個Unicode轉換成三個byte,若是此時用ISO-8859-1構造字符串就會出現三個問號;用GBK構造字符串就會出現雜碼,如a涓枃。數組
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/qinysong/archive/2006/09/05/1179489.aspxide