java中文亂碼解決之道(一)—–認識字符集

原文地址:http://cmsblogs.com/?p=1395

沉寂了許久(大概有三個多月了吧),LZ“按捺不住”開始寫博了!

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需要另起一篇詳細介紹,所以各位看客就簡單看看吧!!)

1.ASCII編碼

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個小寫英文字母,其餘爲一些標點符號、運算符號等。

2014112400001

2014112400002

2.GBK***編碼

ASCII最大的缺點就是顯示字符有限,他雖然解決了部分西歐語言的顯示問題,但是對更多的其他語言他實在是無能爲了。隨着計算機技術的發展,使用範圍越來越廣泛了,ASCII的缺陷越來越明顯了,其他國家和地區需要使用計算機,必須要設計一套符合本國/本地區的編碼規則。例如爲了顯示中文,我們就必須要設計一套編碼規則用於將漢字轉換爲計算機可以接受的數字系統的數。

GB2312,用於漢字處理、漢字通信等系統之間的信息交換,通行於中國大陸。它的編碼規則是:小於127的字符的意義與原來相同,但兩個大於127的字符連在一起時,就表示一個漢字,前面的一個字節(他稱之爲高字節)從0xA1用到 0xF7,後面一個字節(低字節)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了。雖然GB2312收錄了這麼多漢子,他所覆蓋的使用率可以達到99%,但是對於那些不常見的漢字,例如人名、地名、古漢語,它就不能處理了,於是就有下面的GBK、GB 18030的出現。(點擊GB2312簡體中文編碼表查看)。

GB18030全稱:國家標準GB 18030-2005《信息技術 中文編碼字符集》,是我國計算機系統必須遵循的基礎性標準之一,GB18030有兩個版本:GB18030-2000和GB18030-2005。GB18030-2000是GBK的取代版本,它的主要特點是在GBK基礎上增加了CJK統一漢字擴充A的漢字。

GB 18030主要有以下特點:

    與UTF-8相同,採用多字節編碼,每個字可以由1個、2個或4個字節組成。

    編碼空間龐大,最多可定義161萬個字符。

    支持中國國內少數民族的文字,不需要動用造字區。

    漢字收錄範圍包含繁體漢字以及日韓漢字

2014112400003

GBK,漢字編碼標準之一,全稱《漢字內碼擴展規範》,它 向下與 GB 2312 編碼兼容,向上支持 ISO 10646.1 國際標準,是前者向後者過渡過程中的一個承上啓下的標準。它的編碼範圍如下圖:

2014112400004

3.Unicode編碼

正如前面前面所提到的一樣,世界存在這麼多國家,也存在着多種編碼風格,像中文的GB232、GBK、GB18030,這樣亂搞一套,雖然在本地運行沒有問題,但是一旦出現在網絡上,由於互不兼容,訪問則會出現亂碼。爲了解決這個問題,偉大的Unicode編碼騰空出世。

Unicode編碼的作用就是能夠使計算機實現誇平臺、跨語言的文本轉換和處理。它幾乎包含了世界上所有的符號,並且每個符號都是獨一無二的。在它的編碼世界裏,每一個數字代表一個符號,每一個符號代表了一個數字,不存在二義性。

Unicode編碼又稱統一碼、萬國碼、單一碼,它是業界的一種標準,是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。同時Unicode是字符集,它存在很多幾種實現方式如:UTF-8、UTF-16.

UTF-8

互聯網的普及,強烈要求出現一種統一的編碼方式。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碼。

推薦閱讀

此篇博文只是開篇之作,啓下之用, 對字符集的介紹也只是簡簡單單,沒有太多的描述,因爲LZ在查字符集的資料過程中發現字符集真的是太複雜了,LZ有點兒駕馭不了,需要仔細研究,然後寫一篇較爲詳細的博文!各位敬請期待!!

參考文獻:

字符集和字符編碼http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

百度百科 ASCII:http://baike.baidu.com/view/15482.htm

百度百科:GB2312:http://baike.baidu.com/view/443268.htm?fromtitle=GB2312&fromid=483170&type=syn

百度百科:GB18030:http://baike.baidu.com/view/889058.htm

百度百科:GBK:http://baike.baidu.com/view/931619.htm?fromtitle=GBK&fromid=481954&type=search

百度百科:Unicode:http://baike.baidu.com/view/40801.htm

百度百科:UTF-8:http://baike.baidu.com/view/25412.htm

如有錯誤之處,忘指出!!不勝感激!!!

發佈了15 篇原創文章 · 獲贊 26 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章