在編程方面常常遇到字符編碼的問題,因爲對字符集沒有一個系統的認識,老是被亂碼搞得一頭霧水,這篇博文則是對字符編碼方面的進行了一下整理,以便往後複習。在學習字符集的過程當中,我主要從字符集的(a)編碼方式,(b)佔用字節,兩個方面來進行分析的。前端
參考資料:ISO-8859-1編程
ISO-8859-1(Latin1)編碼是單字節編碼,向下兼容ASCII,其編碼範圍是0x00-0xFF,0x00-0x7F之間徹底和ASCII一致,0x80-0x9F之間是控制字符,0xA0-0xFF之間是文字符號。由於ISO-8859-1編碼範圍使用了單字節內的全部空間,在支持ISO-8859-1的系統中傳輸和存儲其餘任何編碼的字節流都不會被拋棄。換言之,把其餘任何編碼的字節流看成ISO-8859-1編碼看待都沒有問題。下圖爲ISO-8859-1字符集(包括ASCII字符集,圖片來自百科)的編碼表,編碼方式數組
在下面代碼中,字符串str"úù§ABD"的前三個字符因爲不在ASCII編碼範圍內,故變量asc不能還原爲源字符串。由byte數組的長度來看,ISO-8859-1和ASCII爲單字節編碼。學習
1 public static void iso(){ 2 String str = "úù§ABD"; 3 try { 4 byte[] ch = str.getBytes("ISO-8859-1"); 5 String asc = new String(ch, "ASCII"); 6 String iso = new String(ch, "ISO-8859-1"); 7 System.out.println(str+" length:"+ch.length+" bytecode:"+byte2hex(ch)+"\nASCII:"+asc +"\nISO-8859-1:"+iso); 8 } catch (UnsupportedEncodingException e) { 9 // TODO Auto-generated catch block 10 e.printStackTrace(); 11 } 12 }
OUTPUT:測試
úù§ABD length:6 bytecode: fa f9 a7 41 42 44
ASCII:???ABD
ISO-8859-1:úù§ABD編碼
GBK全稱《漢字內碼擴展規範》,GBK編碼,是在GB2312-80標準基礎上的內碼擴展規範,使用了雙字節編碼方案,其編碼範圍從8140至FEFE(剔除xx7F),共23940個碼位,共收錄了21003個漢字。GBK爲對GB2312的一次擴充,其高位字節再也不要求區號加0xA0,低位字節甚至不要求首位bit爲1,這樣大大擴充了GB2312的可編碼範圍。spa
1 public static void gb(){ 2 String str = "啊aA"; 3 byte[] ch; 4 try { 5 ch = str.getBytes("GB2312"); 6 System.out.println("ch length:"+ch.length+" bytecode:"+byte2hex(ch)); 7 ch = str.getBytes("GBK"); 8 System.out.println("ch length:"+ch.length+" bytecode:"+byte2hex(ch)); 9 } catch (UnsupportedEncodingException e) { 10 // TODO Auto-generated catch block 11 e.printStackTrace(); 12 } 13 }
OUTPUT:.net
ch length:4 bytecode: b0 a1 61 41
ch length:4 bytecode: b0 a1 61 41code
從程序能夠看出GB2312,GBK是不定長的,漢字爲2個字節,英文字符爲一個字節。因爲表示漢字或圖形符號的「高位字節」的首個bit都爲1,而ASCII首個bit爲0,而實現了這兩種字符集對ASCII的兼容。
參考資料:Unicode, UTF-8, UTF-16, UTF-32, 通用字符集
Unicode伴隨着通用字符集的標準而發展,Unicode至今仍在不斷增修,每一個新版本都加入更多新的字符。目前最新的版本爲2014年6月16日公佈的7.0.0。實際應用的Unicode版本對應於UFT-16。Unicode一般會用「U+」而後緊接着4個十六進制的數字來對應一個經常使用字符,如」U+4EA0「表明某一個字符,若須要表示更多的字符則須要使用五位或六位十六進制數,這是Unicode對字符的表示方式。
UTF(Unicode transfromation format)是Unicode的不一樣實現,這裏的實現指的是字符在計算機中的表示方式。
UTF-8是一種針對Unicode的可變長度字符編碼,它能夠用來表示Unicode標準中的任何字元,且其編碼中的第一個字節仍與ASCII兼容。下圖是字符在UTF-8中的編碼方式,UTF-8可能使用三、4或更多個字節表示一個字符。
UTF-16使用兩個字節表示經常使用的字符(碼位從U+0000至U+FFFF),對於超出U+FFFF外的字符須要4字節表示,這裏僅表示大體理解,深刻了解請查看維基百科UTF-16。
UTF-32是另外一種將Unicode字符編碼的協議,對每個Unicode碼位均使用定長的4字節來表示。
1 public static void unicode(){ 2 String str1 = "中文測試"; 3 byte[] ch; 4 try { 5 ch = str1.getBytes("unicode"); 6 System.out.println(str1+" length:"+ch.length+" unicode:"+byte2hex(ch)); 7 ch = str1.getBytes("utf-8"); 8 System.out.println(str1+" length:"+ch.length+" utf-8:"+byte2hex(ch)); 9 ch = str1.getBytes("utf-16"); 10 System.out.println(str1+" length:"+ch.length+" utf-16:"+byte2hex(ch)); 11 ch = str1.getBytes("utf-32"); 12 System.out.println(str1+" length:"+ch.length+" utf-32:"+byte2hex(ch)); 13 str1 = "test"; 14 ch = str1.getBytes("unicode"); 15 System.out.println(str1+" length:"+ch.length+" unicode:"+byte2hex(ch)); 16 ch = str1.getBytes("utf-8"); 17 System.out.println(str1+" length:"+ch.length+" utf-8:"+byte2hex(ch)); 18 ch = str1.getBytes("utf-16"); 19 System.out.println(str1+" length:"+ch.length+" utf-16:"+byte2hex(ch)); 20 ch = str1.getBytes("utf-32"); 21 System.out.println(str1+" length:"+ch.length+" utf-32:"+byte2hex(ch)); 22 } catch (UnsupportedEncodingException e) { 23 // TODO Auto-generated catch block 24 e.printStackTrace(); 25 } 26 }
OUTPUT:
中文測試 length:10 unicode: fe ff 4e 2d 65 87 6d 4b 8b d5
中文測試 length:12 utf-8: e4 b8 ad e6 96 87 e6 b5 8b e8 af 95
中文測試 length:10 utf-16: fe ff 4e 2d 65 87 6d 4b 8b d5
中文測試 length:16 utf-32: 00 00 4e 2d 00 00 65 87 00 00 6d 4b 00 00 8b d5
test length:10 unicode: fe ff 00 74 00 65 00 73 00 74
test length:4 utf-8: 74 65 73 74
test length:10 utf-16: fe ff 00 74 00 65 00 73 00 74
test length:16 utf-32: 00 00 00 74 00 00 00 65 00 00 00 73 00 00 00 74
從實驗結果來看,UTF-8使用3個字節表示中文字符,1字節表示英文字符。UTF-32使用4個字節來表示每一種字符。在Unicode和UTF-16用兩個字節表示中英文字符,且前端均有一個feff字節,該字節爲BOM(Byte Order Mark)表示字節讀取順序。
本文主要記錄了做者學習字符集的過程,若有錯誤,望諒解指正。想要了解下字符集的發展過程,這篇風趣的文章有所介紹:http://blog.csdn.net/aisq2008/article/details/6298170