830
技術社區[雲棲]
java中文亂碼解決之道(一)—–認識字符集
java編碼中的中文問題是一個老生常談的問題了,每次遇到中文亂碼LZ要麼是按照以前的經驗修改,要麼則是baidu.com來解決問題。閱讀許多關於中文亂碼的解決辦法的博文後,發現對於該問題我們都(更加包括我自己)沒有一個清晰明了的認識,於是LZ想通過這係列博文(估計隻有幾篇)來徹底分析、解決java中文亂碼問題,如有錯誤之處望各位同仁指出!當然,此係列博文並非LZ完全原創,都是在前輩基礎上總結,歸納,如果雷同純屬借鑒……
對於計算機而言,它僅認識兩個0和1,不管是在內存中還是外部存儲設備上,我們所看到的文字、圖片、視頻等等“數據”在計算機中都是已二進製形式存在的。不同字符對應二進製數的規則,就是字符的編碼。字符編碼的集合稱為字符集。
在早期的計算機係統中,使用的字符是非常少的,他們隻包括26個英文字母、數字符號和一些常用符號,對於這些字符進行編碼,用1個字節就足夠了,但是隨著計算機的不斷發展,為了適應全世界其他各國民族的語言,這些少得可憐的字符編碼肯定是不夠的。於是人們提出了UNICODE編碼,它采用雙字節編碼,兼容英文字符和其他國家民族的雙字節字符編碼。
每個國家為了統一編碼都會規定該國家/地區計算機信息交換用的字符集編碼,為了解決本地字符信息的計算機處理,於是出現了各種本地化版本,引進LANG, Codepage 等概念。現在大部分具有國際化特征的軟件核心字符處理都是以 Unicode 為基礎的,在軟件運行時根據當時的 Locale/Lang/Codepage 設置確定相應的本地字符編碼設置,並依此處理本地字符。在處理過程中需要實現 Unicode 和本地字符集的相互轉換。
同然,java內部采用的就是Unicode編碼,所以在java運行的過程中就必然存在從Unicode編碼與相應的計算機操作係統或者瀏覽器支持的編碼格式相互轉化的過程,這個轉換的過程有一係列的步驟,如果某個步驟出現錯誤,則輸出的文字就會是亂碼。
所以產生java亂碼的問題就在於JVM與對應的操作係統/瀏覽器進行編碼格式轉換時出現了錯誤。
其實要解決java亂碼問題的方法還是比較簡單的,但是要究其原因,理解背後的原理還是需要了解
其實解決 JAVA 程序中的漢字編碼問題的方法往往很簡單,但理解其背後的原因,定位問題,還需要了解現有的漢字編碼和編碼轉換。
計算機要準確的處理各種字符集文字,需要進行字符編碼,以便計算機能夠識別和存儲各種文字。常見的字符編碼主要包括:ASCII編碼、GB**編碼、Unicode。下麵LZ就簡單地介紹下!(為什麼是簡單介紹?因為LZ在網上查找資料想去了解字符編碼時,發現這個問題比我想象的複雜太多了,所以LZ需要另起一篇詳細介紹,所以各位看客就簡單看看吧!!)
ASCII,American Standard Code for Information Interchange,是基於拉丁字母的一套電腦編碼係統,主要用於顯示現代英語和其他西歐語言。它是現今最通用的單字節編碼係統。
ASCII碼使用指定的7位或者8為二進製數字組合表示128或者256種可能的字符。標準的ASCII編碼使用的是7(2^7 = 128)位二進製數來表示所有的大小寫字母、數字和標點符號已經一些特殊的控製字符,最前麵的一位統一規定為0。其中0~31及127(共33個)是控製字符或通信專用字符,32~126(共95個)是字符(32是空格),其中48~57為0到9十個阿拉伯數字,65~90為26個大寫英文字母,97~122號為26個小寫英文字母,其餘為一些標點符號、運算符號等。
ASCII最大的缺點就是顯示字符有限,他雖然解決了部分西歐語言的顯示問題,但是對更多的其他語言他實在是無能為了。隨著計算機技術的發展,使用範圍越來越廣泛了,ASCII的缺陷越來越明顯了,其他國家和地區需要使用計算機,必須要設計一套符合本國/本地區的編碼規則。例如為了顯示中文,我們就必須要設計一套編碼規則用於將漢字轉換為計算機可以接受的數字係統的數。
GB2312,用於漢字處理、漢字通信等係統之間的信息交換,通行於中國大陸。它的編碼規則是:小於127的字符的意義與原來相同,但兩個大於127的字符連在一起時,就表示一個漢字,前麵的一個字節(他稱之為高字節)從0xA1用到 0xF7,後麵一個字節(低字節)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了。雖然GB2312收錄了這麼多漢子,他所覆蓋的使用率可以達到99%,但是對於那些不常見的漢字,例如人名、地名、古漢語,它就不能處理了,於是就有下麵的GBK、GB 18030的出現。
GB18030,全稱:國家標準GB 18030-2005《信息技術 中文編碼字符集》,是我國計算機係統必須遵循的基礎性標準之一,GB18030有兩個版本:GB18030-2000和GB18030-2005。GB18030-2000是GBK的取代版本,它的主要特點是在GBK基礎上增加了CJK統一漢字擴充A的漢字。
GB 18030主要有以下特點:
- 與UTF-8相同,采用多字節編碼,每個字可以由1個、2個或4個字節組成。
- 編碼空間龐大,最多可定義161萬個字符。
- 支持中國國內少數民族的文字,不需要動用造字區。
- 漢字收錄範圍包含繁體漢字以及日韓漢字
GBK,漢字編碼標準之一,全稱《漢字內碼擴展規範》,它 向下與 GB 2312 編碼兼容,向上支持 ISO 10646.1 國際標準,是前者向後者過渡過程中的一個承上啟下的標準。它的編碼範圍如下圖:
正如前麵前麵所提到的一樣,世界存在這麼多國家,也存在著多種編碼風格,像中文的GB232、GBK、GB18030,這樣亂搞一套,雖然在本地運行沒有問題,但是一旦出現在網絡上,由於互不兼容,訪問則會出現亂碼。為了解決這個問題,偉大的Unicode編碼騰空出世。
Unicode編碼的作用就是能夠使計算機實現誇平台、跨語言的文本轉換和處理。它幾乎包含了世界上所有的符號,並且每個符號都是獨一無二的。在它的編碼世界裏,每一個數字代表一個符號,每一個符號代表了一個數字,不存在二義性。
Unicode編碼又稱統一碼、萬國碼、單一碼,它是業界的一種標準,是為了解決傳統的字符編碼方案的局限而產生的,它為每種語言中的每個字符設定了統一並且唯一的二進製編碼,以滿足跨語言、跨平台進行文本轉換、處理的要求。同時Unicode是字符集,它存在很多幾種實現方式如:UTF-8、UTF-16.
互聯網的普及,強烈要求出現一種統一的編碼方式。UTF-8就是在互聯網上使用最廣的一種unicode的實現方式。其他實現方式還包括UTF-16和UTF-32,不過在互聯網上基本不用。重複一遍:UTF-8是Unicode的實現方式之一。
UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。
UTF-8的編碼規則很簡單,隻有兩條:
1)對於單字節的符號,字節的第一位設為0,後麵7位為這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
2)對於n字節的符號(n>1),第一個字節的前n位都設為1,第n+1位設為0,後麵字節的前兩位一律設為10。剩下的沒有提及的二進製位,全部為這個符號的unicode碼。
最後更新:2017-07-06 16:32:20