中文編碼雜談

編碼問題的例子

在windows自帶的notepad(記事本)程序中輸入“聯通”兩個字,保存后再次打開,會發現“聯通”不見了,代之以“”的亂碼。這是windows平臺上典型的中文編碼問題。即文件保存的時候是按照ANSI編碼(其實就是GB2312,后面會詳細介紹)保存,打開的時候程序按照UTF-8方式對內容解釋,于是就出現了亂碼。避免亂碼的方式很簡單,在“文件”菜單中選擇“打開”命令,選擇保存的文件,然后選擇“ANSI”編碼,此時就能看到久違的“聯通”兩個字了。

在Linux平臺上如果使用cat等命令查看文件中的中文內容時,可能出現亂碼。這也是編碼的問題。簡單的說是文件時按照A編碼保存,但是cat命令按照當前Locale設定的B編碼去查看,在B和A不兼容的時候就出現了亂碼。

為什么寫這篇文章

中文編碼由于歷史原因牽扯到不少標準,在不了解的時候感覺一頭霧水;但其實理解編碼問題并不需要你深入了解各個編碼標準,只要你明白了來龍去脈,了解了關鍵的知識點,就能分析和解決日常開發工作中碰到的大部分編碼問題。有感于我看過的資料和文章要么不夠全面,要么略顯枯燥,所以通過這篇文章記錄下筆者在日常工作中碰到的中文編碼原理相關問題,目的主要是自我總結,如果能給讀者提供一些幫助那就算是意外之喜了。由于嚴謹的編碼標準對我來說是無趣的,枯燥的,難以記憶的,本文嘗試用淺顯易懂的生活語言解釋中文編碼相關的(也可能不相關的)一些問題,這也是為什么取名雜談的原因。本文肯定存在不規范不全面的地方,我會在參考資料里給出官方文檔的鏈接,也歡迎讀者在評論中提出更好的表達方式&指出錯誤,不勝感激。

對編碼問題的理解我認為分為三個層次,第一個層次:概念,知道各個編碼標準的應用場景,了解之間的差異,能分析和解決常見的一些編碼問題。第二個層次:標準,掌握編碼的細節,如編碼范圍,編碼轉換規則,知道這些就能自行開發編碼轉換工具。第三個層次,使用,了解中文的編碼2進制存儲,在程序開發過程中選擇合理的編碼并處理中文。為了避免讓讀者陷入編碼標準的黑洞無法脫身(不相信?看看unicode的規范就明白我的意思了),同時由于編碼查詢&轉換工具等都有現成工具可以使用,本文只涉及第一個層次,不涉及第二層次,在第三層次上會做一些嘗試。在本文的最后提供了相關鏈接供對標準細節感興趣的同學繼續學習。最后,本文不涉及具體軟件的亂碼問題解決,如ssh,shell,vim,screen等,這些話題留給劍豪同學專文闡述。

一切都是因為電腦不識字

電腦很聰明,可以幫我們做很多事情,最開始主要是科學計算,這也是為什么電腦別名計算機。電腦又很笨,在她的腦子里只有數字,即所有的數據在存儲和運算時都要使用二進制數表示。這在最初電腦主要用來處理大量復雜的科學計算時不是什么大問題但是當電腦逐步走入普通人的生活時,情況開始變遭了。辦公自動化等領域最主要的需求就是文字處理,電腦如何來表示文字呢?這個問題當然難不倒聰明的計算機科學家們,用數字來代表字符唄。這就是“編碼”。

英文的終極解決方案:ASCII

每個人都可以約定自己的一套編碼,只要使用方之間了解就ok了。比如說咱倆約定0×10表示a,0×11表示b。在一開始也的確是這樣的,出現了各式各樣的編碼。這樣有兩個問題:1.各個編碼的字符集不一樣,有的多,有的少。2.相同字符的編碼也不一樣。你這里a是0×10.他那里a可能是0×30。于是你保存的文件他就不能直接用,必須要轉換編碼。隨著溝通范圍的擴大,采用不同編碼的人們互相通信就亂套了,這就是我們常說的:雞同鴨講。如果要避免這種混亂,那么大家就必須使用相同的編碼規則,于是美國有關的標準化組織就出臺了ASCII(American Standard Code for Information Interchange)編碼,統一規定了英文常用符號用哪些二進制數來表示。ASCII是標準的單字節字符編碼方案,用于基于文本的數據。

ASCII最初是美國國家標準,供不同計算機在相互通信時用作共同遵守的西文字符編碼標準,已被國際標準化組織(International Organization for Standardization, ISO)定為國際標準,稱為ISO 646標準。適用于所有拉丁文字字母。ASCII 碼使用指定的7 位或8 位二進制數組合來表示128 或256 種可能的字符。標準ASCII 碼也叫基礎ASCII碼,使用7 位二進制數來表示所有的大寫和小寫字母,數字0 到9、標點符號, 以及在美式英語中使用的特殊控制字符。而最高位為1的另128個字符(80H—FFH)被稱為“擴展ASCII”,一般用來存放英文的制表符、部分音標字符等等的一些其它符號。

其中:0~31及127(共33個)是控制字符或通信專用字符(其余為可顯示字符),32~126(共95個)是字符(32是空格),其中48~57為0到9十個阿拉伯數字,65~90為26個大寫英文字母,97~122號為26個小寫英文字母,其余為一些標點符號、運算符號等。

ascii 編碼表

現在所有使用英文的電腦終于可以用同一種編碼來交流了。理解了ASCII編碼,其他字母型的語言編碼方案就觸類旁通了。

一波三折的中文編碼

第一次嘗試:GB2312

ASCII這種字符編碼規則顯然用來處理英文沒有什么問題,它的出現極大的促進了信息在西方尤其是美國的傳播和交流。但是對于中文,常用漢字就有6000以上,ASCII 單字節編碼顯然是不夠用。為了粉碎美帝國主義通過編碼限制中國人民使用電腦的無恥陰謀,中國國家標準總局發布了GB2312碼即中華人民共和國國家漢字信息交換用編碼,全稱《信息交換用漢字編碼字符集——基本集》,1981年5月1日實施,通行于大陸。GB2312字符集中除常用簡體漢字字符外還包括希臘字母、日文平假名及片假名字母、俄語西里爾字母等字符,未收錄繁體中文漢字和一些生僻字。 EUC-CN可以理解為GB2312的別名,和GB2312完全相同。

GB2312是基于區位碼設計的,在區位碼的區號和位號上分別加上A0H就得到了GB2312編碼。這里第一次提到了“區位碼”,我就連帶把下面這幾個讓人摸不到頭腦的XX碼一鍋端了吧:

區位碼,國標碼,交換碼,內碼,外碼

區位碼:就是把中文常用的符號,數字,漢字等分門別類進行編碼。區位碼把編碼表分為94個區,每個區對應94個位,每個位置就放一個字符(漢字,符號,數字都屬于字符)。這樣每個字符的區號和位號組合起來就成為該漢字的區位碼。區位碼一般用10進制數來表示,如4907就表示49區7位,對應的字符是“學”。區位碼中01-09區是符號、數字區,16-87區是漢字區,10-15和88-94是未定義的空白區。它將收錄的漢字分成兩級:第一級是常用漢字計3755個,置于16-55區,按漢語拼音字母/筆形順序排列;第二級漢字是次常用漢字計3008個,置于56-87區,按部首/筆畫順序排列。在網上搜索“區位碼查詢系統”可以很方便的找到漢字和對應區位碼轉換的工具。為了避免廣告嫌疑和死鏈,這里就不舉例了。

國標碼: 區位碼無法用于漢字通信,因為它可能與通信使用的控制碼(00H~1FH)(即0~31,還記得ASCII碼特殊字符的范圍嗎?)發生沖突。于是ISO2022規定每個漢字的區號和位號必須分別加上32(即二進制數00100000,16進制20H),得到對應的國標交換碼,簡稱國標碼,交換碼,因此,“學”字的國標交換碼計算為:

1

2

3

4

00110001 00000111

+ 00100000 00100000

-------------------

01010001 00100111

用十六進制數表示即為5127H。

交換碼:即國標交換碼的簡稱,等同上面說的國標碼。

內碼:由于文本中通常混合使用漢字和西文字符,漢字信息如果不予以特別標識,就會與單字節的ASCII碼混淆。此問題的解決方法之一是將一個漢字看成是兩個擴展ASCII碼,使表示GB2312漢字的兩個字節的最高位都為1。即國標碼加上128(即二進制數10000000,16進制80H)這種高位為1的雙字節漢字編碼即為GB2312漢字的機內碼,簡稱為內碼。20H+80H=A0H。這也就是常說的在區位碼的區號和位號上分別加上A0H就得到了GB2312編碼的由來。

1

2

3

4

00110001 00000111

+ 10100000 10100000

-------------------

11010001 10100111

用十六進制數表示即為D1A7H。

外碼:機外碼的簡稱,就是漢字輸入碼,是為了通過鍵盤字符把漢字輸入計算機而設計的一種編碼。 英文輸入時,相輸入什么字符便按什么鍵,外碼和內碼一致。漢字輸入時,可能要按幾個鍵才能輸入一個漢字。 漢字輸入方案有成百上千個,但是這千差萬別的外碼輸入進計算機后都會轉換成統一的內碼。

最后總結一下上面的概念。中國國家標準總局把中文常用字符編碼為94個區,每個區對應94個位,每個字符的區號和位號組合起來就是該字符的區位碼, 區位碼用10進制數來表示,如4907就表示49區7位,對應的字符是“學”。 由于區位碼的取值范圍與通信使用的控制碼(00H~1FH)(即0~31)發生沖突。每個漢字的區號和位號分別加上32(即16進制20H)得到國標碼,交換碼。“學”的國標碼為5127H。由于文本中通常混合使用漢字和西文字符,為了讓漢字信息不會與單字節的ASCII碼混淆,將一個漢字看成是兩個擴展ASCII碼,即漢字的兩個字節的最高位置為1,得到的編碼為GB2312漢字的內碼。“學”的內碼為D1A7H。無論你使用什么輸入法,通過什么樣的按鍵組合把“學”輸入計算機,“學”在使用GB2312(以及兼容GB2312)編碼的計算機里的內碼都是D1A7H。

第二次嘗試:GBK

GB2312的出現基本滿足了漢字的計算機處理需要,但由于上面提到未收錄繁體字和生僻字,從而不能處理人名、古漢語等方面出現的罕用字,這導致了1995年《漢字編碼擴展規范》(GBK)的出現。GBK編碼是GB2312編碼的超集,向下完全兼容GB2312,兼容的含義是不僅字符兼容,而且相同字符的編碼也相同,同時在字匯一級支持ISO/IEC10646—1和GB 13000—1的全部中、日、韓(CJK)漢字,共計20902字。GBK還收錄了GB2312不包含的漢字部首符號、豎排標點符號等字符。CP936和GBK的有些許差別,絕大多數情況下可以把CP936當作GBK的別名。

第三次嘗試:GB18030

GB18030編碼向下兼容GBK和GB2312。GB18030收錄了所有Unicode3.1中的字符,包括中國少數民族字符,GBK不支持的韓文字符等等,也可以說是世界大多民族的文字符號都被收錄在內。GBK和GB2312都是雙字節等寬編碼,如果算上和ASCII兼容所支持的單字節,也可以理解為是單字節和雙字節混合的變長編碼。GB18030編碼是變長編碼,有單字節、雙字節和四字節三種方式。

其實,這三個標準并不需要死記硬背,只需要了解是根據應用需求不斷擴展編碼范圍即可。從GB2312到GBK再到GB18030收錄的字符越來越多即可。萬幸的是一直是向下兼容的,也就是說一個漢字在這三個編碼標準里的編碼是一模一樣的。這些編碼的共性是變長編碼,單字節ASCII兼容,對其他字符GB2312和GBK都使用雙字節等寬編碼,只有GB18030還有四字節編碼的方式。這些編碼最大的問題是2個。1.由于低字節的編碼范圍和ASCII有重合,所以不能根據一個字節的內容判斷是中文的一部分還是一個獨立的英文字符。2.如果有兩個漢字編碼為A1A2B1B2,存在A2B1也是一個有效漢字編碼的特殊情況。這樣就不能直接使用標準的字符串匹配函數來判斷一個字符串里是否包含某一個漢字,而需要先判斷字符邊界然后才能進行字符匹配判斷。

最后,提一個小插曲,上面講的都是大陸推行的漢字編碼標準,使用繁體的中文社群中最常用的電腦漢字字符集標準叫大五碼(Big5),共收錄13,060個中文字,其中有二字為重覆編碼(實在是不應該)。Big5雖普及于中國的臺灣、香港與澳門等繁體中文通行區,但長期以來并非當地的國家標準,而只是業界標準。倚天中文系統、Windows等主要系統的字符集都是以Big5為基準,但廠商又各自增刪,衍生成多種不同版本。2003年,Big5被收錄到臺灣官方標準的附錄當中,取得了較正式的地位。這個最新版本被稱為Big5-2003。

天下歸一Unicode

看了上面的多個中文編碼是不是有點頭暈了呢?如果把這個問題放到全世界n多個國家n多語種呢?各國和各地區自己的文字編碼規則互相沖突的情況全球信息

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452210.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452210.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452210.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java NIO (十四)NIO 和 IO 的區別和適用場景分析

在研究Java NIO和IO API時,很快就會想到一個問題: 什么時候應該使用IO,什么時候應該使用NIO? 在本文中,我將嘗試闡明Java NIO和IO之間的區別,它們的用例以及它們如何影響代碼的設計。 ###Java NIO和IO之間的…

面向對象三種模型之間的關系

功能模型指明了系統應該“做什么”;動態模型明確規定了什么時候(即在何種狀態下接受了什么事件的觸發)做;對象模型則定義了做事情的實體。在面向對象方法學中,對象模型是最基本最重要的,它為其他兩種模型奠定了基礎,人…

android node

pkg install nodejs-current轉載于:https://www.cnblogs.com/insight0912/p/9231342.html

springmvc 中@Controller和@RestController的區別

1.Controller, RestController的共同點 都是用來表示Spring某個類的是否可以接收HTTP請求 2.Controller, RestController的不同點 Controller標識一個Spring類是Spring MVC controller處理器 RestController: a convenience annotation that does nothing more …

easyUI 日期控件修改...

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 個人覺得easyUI挺好用的。 它的中文文檔地址: http://www.zi-han.net/case/easyui/ 日期本來效果是這樣的: 改…

面向對象分析的三個模型與5個層次

在面向對象分析中,主要由對象模型、動態模型和功能模型組成。對象模型是最基本、最重要、最核心的。 面向對象建模得到的模型包含系統的3個要素,即靜態結構(對象模型)、交互次序(動態模型)和數據變換(功能模型)。解決的問題不同,這3個子模型…

學成在線--15.課程計劃查詢

文章目錄一.需求分析二.頁面原型1.tree組件介紹2.webstorm配置jsx三.API接口1.數據模型2.自定義模型類3.接口定義四.sql語句五.服務器端1.Dao1)Mapper接口2)Mapper映射文件2.Service3.Controller4.測試六.前端1.Api方法2.Api調用1)定義查詢課…

團隊作業-項目答辯

1. 王書磊 1600802063 http://www.cnblogs.com/wsl-1117/ 劉令斌 1600802017 http://www.cnblogs.com/liulingbin/ 許浩然 1600802066 https://www.cnblogs.com/xuhaoran1/ 成明龍 1600802038 http://www.cnblogs.com/CMLCML/ 2這是我們的效果圖. 3.(1)修…

Java構造和解析Json數據的兩種方法詳解一

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 在www.json.org上公布了很多JAVA下的json構造和解析工具,其中org.json和json-lib比較簡單,兩者使用上差不多但還是…

面向對象方法開發的方法

面向對象分析首要的工作,是建立問題域的對象模型。 這個模型描述了現實世界中的“類與對象”以及它們之間的關系,表示了目標系統的靜態數據結構。靜態數據結構對應用細節依賴較少,比較容易確定。因此,用面向對象方法開發絕大多數…

程序員編程需要多少個小時?

Michael Arrington曾發表一篇博文說,創業者必須加倍的努力工作,甚至不惜趴在辦公桌上睡覺,這樣才能成功。對此,我并不贊同其觀點,我看了很多評論都是關于這樣工作會適得其反,不但沒有獲得成功,相…

事務以及@Transcational注解

文章目錄1.事務的概念2.事務的四個特性3.關于Transcational注解的理解4.使用場景5.舉例6.編程式事務管理7.相關知識1.事務的概念 事務,是指作為單個邏輯工作單元執行的一系列操作,結果只有成功和失敗兩種,要么全部成功(全部提交)&#xff0c…

提高代碼復用率

由于現在的互聯網企業業務比較繁忙,導致產品狗不停地提需求,還總是改來改去,最后留給程序猿的時間少之又少。程序猿也不是吃素的,干脆直接copy一下代碼隨便搞一下實現功能就行,也談不上所謂的精心設計了。這樣的確是縮…

java 對 redis 的基本操作

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 一、server端安裝 1、下載https://github.com/MSOpenTech/redis 可看到當前可下載版本:redis2.6 2、安裝 1)解壓…

JsRender 前端渲染模板常用API學習

JsRender 常用API 1. $.templates() $.templates()方法是用來注冊或編譯模板的,使用的情況有以下幾種。 把html字符串編譯編譯成模板獲取使用script標簽聲明的模板,并返回一個模板對象把html字符串或者在script標簽中聲明的模板注冊成命名模板獲取之前就…

狀態圖

狀態圖(Statechart Diagram)是描述一個實體基于事件反應的動態行為,顯示了該實體如何根據當前所處的狀態對不同的事件做出反應。通常我們創建一個UML狀態圖是為了以下的研究目的:研究類、角色、子系統、或組件的復雜行為。

我身邊的手機應用開發者

手機應用火了,我身邊的一位朋友(A君)也投身到開發者行列,不過他還算聰明并沒有辭掉工作專做手機應用軟件開發。 其原因在于他們領導打算做一款自己的應用軟件,正當A君愁到底是做IOS平臺還是Android平臺的時候,領導說:…

學成在線--16.添加課程計劃

文章目錄一.需求分析二.API接口三.后端1.Dao2.Service3.Controller4.測試四.前端1.頁面原型說明1)添加按鈕2)視圖部分3)在數據模型中添加如下變量4)定義表單提交方法和重置方法2.Api調用1)定義 api方法2)調…

mac 下的操作

nodejs在Mac下的卸載 在 node 官網上下載的安裝包,用安裝包安裝的node.應該可以用一下命令行卸載: 在終端輸入以下命令: sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node.*} 刪除/usr/local/lib中的…

理解 maven 的核心概念

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 本文以類圖的方式,介紹 maven 核心的 12 個概念及相互之間的關系。 Table of Contents 1 maven管理的目標:工程…