【JAVA编码】 JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
生活随笔
收集整理的這篇文章主要介紹了
【JAVA编码】 JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://blog.csdn.net/qinysong/article/details/1179489
這兩天抽時間又總結/整理了一下各種編碼的實際編碼方式,和在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涓枃。
這兩天抽時間又總結/整理了一下各種編碼的實際編碼方式,和在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涓枃。
總結
以上是生活随笔為你收集整理的【JAVA编码】 JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【JAVA编码专题】JAVA字符编码系列
- 下一篇: 【JAVA编码专题】 JAVA字符编码系