【转】刨根究底字符编码之五——简体汉字编码方案(GB2312、GBK等)以及全角、半角、CJK
一、概述
1.
英文字母再加一些其他標(biāo)點字符之類的也不會超過256個,用一個字節(jié)來表示一個字符就足夠了(2^8 = 256)。但其他一些文字不止這么多字符,比如中文中的漢字就多達(dá)10多萬個,一個字節(jié)只能表示256個字符,肯定是不夠的,因此只能使用多個字節(jié)來表示一個字符。
于是當(dāng)計算機被引入到中國后,相關(guān)部門設(shè)計了GB系列編碼(“GB”為“國標(biāo)”的漢語拼音首字母縮寫,即“國家標(biāo)準(zhǔn)”之意)。
按照GB系列編碼方案,在一段文本中,如果一個字節(jié)是0~127,那么這個字節(jié)的含義與ASCII編碼相同,否則,這個字節(jié)和下一個字節(jié)共同組成漢字(或是GB編碼定義的其他字符)。
因此,GB系列編碼方案向下完全直接兼容ASCII編碼方案。也就是說,如果一段用GB編碼方案編碼的文本里的所有字符都在ASCII編碼方案中有定義(即該文本全部由ASCII字符組成),那么這段GB編碼實際上和ASCII編碼完全一樣。
2.
最早的GB編碼方案是GB2312,收錄的漢字不足一萬個,基本能滿足日常使用需求,但不包含一些生僻字,因此后來又在GB2312基礎(chǔ)上進(jìn)行了擴展。
在GB2312基礎(chǔ)上擴展的編碼方案稱之為GBK(K為“擴展”的拼音首字母),后來又在GBK的基礎(chǔ)上進(jìn)一步擴展,稱之為GB18030,加入了一些國內(nèi)少數(shù)民族的文字,一些生僻字被編到了4個字節(jié)。
包括GB2312、GBK、GB18030在內(nèi)的GB系列編碼方案(不包括GB13000,下同,不再贅述;GB13000編碼方案下文有詳解介紹),每擴展一次都完全保留之前版本的編碼,所以每個新版本都向下兼容。
這里要指出的是,雖然都用多個字節(jié)表示一個字符,但是GB類的漢字編碼與后文的Unicode編碼方案的UTF-8、UTF-16、UTF-32等字符編碼方式CEF是毫無關(guān)系的(其中UTF-8對于ASCII字符仍用一個字節(jié)編碼,而非ASCII字符則為多字節(jié)編碼)。
3.
不過,也正因為不得不使用多個字節(jié)來表示一個字符,相較于只使用單個字節(jié)的ASCII編碼方案,GB系列編碼方案與后面要介紹的Unicode編碼方案一樣,無疑導(dǎo)致了更高的復(fù)雜度(包括時間復(fù)雜度、空間復(fù)雜度等)。
比如,當(dāng)多字節(jié)字符與原先的ASCII字符混用時:
1)要么將原先的ASCII字符重新編碼為多個字節(jié)表示,以便與其他多字節(jié)字符統(tǒng)一起來(UTF-16、UTF-32等采用的就是這種方法);
2)要么保持ASCII字符為單個字節(jié)編碼不變,但將其他多字節(jié)字符編碼中的各個字節(jié)的最高位(即首位)設(shè)為1,以避免與字節(jié)最高位為0的ASCII編碼相沖突(GB、UTF-8等采用的就是這種方法)。
前者具有更高的空間復(fù)雜度,因為原先只需要單個字節(jié)表示的ASCII字符,現(xiàn)在也必須用多個字節(jié)來表示,顯然更為耗費存儲空間;后者則具有更高的時間復(fù)雜度,因為為了避免沖突以及其他種種考慮(比如擴展性、容錯性等),使用了更為復(fù)雜的編碼算法(Encoding Algorithm),無疑更為耗費計算時間。
而且,無論是前者還是后者,若多字節(jié)編碼中采用的又是多字節(jié)碼元(Code Unit)的話(如UTF-16、UTF-32編碼采用的就是多字節(jié)碼元,而UTF-8中的非ASCII字符雖然也是多字節(jié)編碼,但采用的卻是單字節(jié)碼元;注意,GB系列編碼雖然除ASCII字符外的其余字符為多字節(jié)編碼,但采用的仍然是單字節(jié)碼元),由于歷史的原因,又進(jìn)一步引發(fā)了更為麻煩的字節(jié)序(Byte-Order)問題。(編碼算法、碼元、字節(jié)序的相關(guān)介紹,詳見后文解釋)
?
二、GB2312
1.
GB2312編碼方案,即《信息交換用漢字編碼字符集——基本集》,是由中國國家標(biāo)準(zhǔn)總局于1980年發(fā)布、1981年5月1日開始實施的一套國家標(biāo)準(zhǔn),標(biāo)準(zhǔn)號為GB2312-1980。
GB2312編碼適用于漢字處理、漢字通信等系統(tǒng)之間的信息交換,通行于中國大陸;新加坡等地也采用此編碼。中國大陸幾乎所有的中文系統(tǒng)和國際化的軟件都支持GB2312。
2.
GB2312編碼為了避免與ASCII字符編碼(0~127)相沖突,規(guī)定表示一個漢字的編碼(即漢字內(nèi)碼)的字節(jié)其值必須大于127(即字節(jié)的最高位為1),并且必須是兩個大于127的字節(jié)連在一起來共同表示一個漢字(GB2312為雙字節(jié)編碼),前一字節(jié)稱為高字節(jié),后一字節(jié)稱為低字節(jié);而一個字節(jié)的值若小于等于127(即字節(jié)的最高位為0),自然是仍表示一個原來的ASCII字符(ASCII為單字節(jié)編碼)。
因此,可以認(rèn)為GB2312是對ASCII的中文擴展(即GB2312完全直接兼容ASCII),正如EASCII是對ASCII的歐洲文字?jǐn)U展一樣。
不過,很顯然的是,GB2312與EASCII碼的128~255這段擴展部分所表示的字符是不同的。也就是說,GB2312與EASCII雖然都兼容ASCII,但GB2312并不兼容EASCII的擴展部分。
事實上,目前世界上除ASCII之外的其它通行的字符編碼方案,基本上都兼容ASCII(包括直接兼容與間接兼容,詳見后文介紹),但相互之間除了兼容ASCII字符的部分之外卻并不兼容。
(笨笨阿林原創(chuàng)文章,轉(zhuǎn)載請注明出處)
3.
GB2312標(biāo)準(zhǔn)共收錄6763個漢字,其中一級漢字3755個,二級漢字3008個;同時,除了漢字,GB2312還收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西里爾字母在內(nèi)的682個字符。
可能是出于顯示上視覺美觀的考慮,除漢字之外的682個字符中,GB2312甚至還包括了ASCII里本來就有的數(shù)字、標(biāo)點、字母等字符。也就是說,這些ASCII里原來就有的單字節(jié)編碼的字符,又再編了兩個字節(jié)長的GB2312編碼版本。
這682個雙字節(jié)編碼字符就是常說的“全角”字符,而這些字符所對應(yīng)的單字節(jié)編碼的ASCII字符就被稱之為“半角”字符。
【附:全角、半角
全角字符是中文顯示及雙字節(jié)中文編碼的歷史遺留問題。
早期的點陣顯示器上由于像素有限,原先ASCII西文字符的顯示寬度(比如8像素的寬度)用來顯示漢字有些捉襟見肘(實際上早期的針式打印機在打印輸出時也存在這個問題),因此就采用了兩倍于ASCII字符的顯示寬度(比如16像素的寬度)來顯示漢字。
這樣一來,ASCII西文字符在顯示時其寬度為漢字的一半。或許是為了在西文字符與漢字混合排版時,讓西文字符能與漢字對齊等視覺美觀上的考慮,于是就設(shè)計了讓西文字母、數(shù)字和標(biāo)點等特殊字符在外觀視覺上也占用一個漢字的視覺空間(主要是寬度),并且在內(nèi)部存儲上也同漢字一樣使用2個字節(jié)進(jìn)行存儲的方案。這些與漢字在顯示寬度上一樣的西文字符就被稱之為全角字符。
而原來ASCII中的西文字符由于在外觀視覺上僅占用半個漢字的視覺空間(主要是寬度),并且在內(nèi)部存儲上使用1個字節(jié)進(jìn)行存儲,相對于全角字符,因而被稱之為半角字符。
后來,其中的一些全角字符因為比較有用,就得到了廣泛應(yīng)用(比如全角的逗號“,”、問號“?”、感嘆號“!”、空格“ ”等,這些字符在輸入法中文輸入狀態(tài)下的半角與全角是一樣的,英文輸入狀態(tài)下全角跟中文輸入狀態(tài)一樣,但半角大約為全角的二分之一寬),專用于中日韓文本,成為了標(biāo)準(zhǔn)的中日韓標(biāo)點字符。而其它的許多全角字符則逐漸失去了價值(現(xiàn)在很少需要讓純文本的中文和西文字符對齊了),就很少再用了。
現(xiàn)在全球字符編碼的事實標(biāo)準(zhǔn)是Unicode字符集及基于此的UTF-8、UTF-16等編碼實現(xiàn)方式。Unicode吸納了許多遺留(legacy)編碼,并且為了兼容性而保留了所有字符。因此中文編碼方案中的這些全角字符也保留下來了,而國家標(biāo)準(zhǔn)也仍要求字體和軟件都支持這些全角字符。
不過,半角和全角字符的關(guān)系在UTF-8、UTF-16等中不再是簡單的1字節(jié)和2字節(jié)的關(guān)系了。具體參見后文。
——綜合了知乎《中文輸入法為什么會有全角和半角的區(qū)別?》下多位答主的回答,有多處修改】
?
三、GBK
1.
GB2312-1980共收錄6763個漢字,覆蓋了中國大陸99.75%的使用頻率,基本滿足了漢字的計算機處理需要。
但對于人名、古漢語等方面出現(xiàn)的罕用字、生僻字,GB2312不能處理,如部分在GB2312-1980推出以后才簡化的漢字(如“啰”)、部分人名用字(如歌手陶喆的“喆”字)、臺灣及香港使用的繁體字、日語及朝鮮語漢字等,并未收錄在內(nèi)。
于是全國信息技術(shù)標(biāo)準(zhǔn)化技術(shù)委員會利用GB2312-1980未使用的碼點空間,收錄GB13000.1-1993的全部字符,于1995年12月1日發(fā)布了《漢字內(nèi)碼擴展規(guī)范(GBK)》(Guo-Biao Kuozhan國家標(biāo)準(zhǔn)擴展碼,是根據(jù)GB13000.1-1993(GB13000下文有詳細(xì)介紹),對GB2312-1980的擴展;英文全稱Chinese Internal Code Specification)。
2.
不過,收錄了GB13000.1-1993全部字符的GBK,雖然是基于GB2312-1980進(jìn)行的擴展,但在編碼方式上與GB2312-1980并不完全相同(與為了跟國際標(biāo)準(zhǔn)ISO/IEC 10646接軌的GB13000.1-1993更是完全不同)。
雖然GBK跟GB2312一樣是雙字節(jié)編碼,但GBK只要求第一個字節(jié)即高字節(jié)大于127就固定表示這是一個漢字的開始(即GBK編碼高字節(jié)的首位必須是1;0~127當(dāng)然表示的還是ASCII字符),不再像GB2312一樣要求第二個字節(jié)即低字節(jié)也必須大于127(即GBK編碼低字節(jié)首位既可以是0,也可以是1)。
正因為如此,作為同樣是雙字節(jié)編碼的GBK才可以收錄比GB2312更多的字符。
GBK字符集向后完全兼容GB2312,同時還支持GB2312-1980不支持的部分中文簡體、中文繁體、日文假名(不過這個編碼不支持韓國文字,也是其在實際使用中與Unicode編碼相比欠缺的部分),共收錄漢字21003個、符號883個,并提供1894個造字碼位,簡、繁體字融于一體。
GBK的編碼框架(Code Scheme):其中GBK/1收錄除GB2312字符外的其他增補字符,GBK/2收錄GB2312字符,GBK/3收錄CJK字符,GBK/4收錄CJK字符和增補字符,GBK/5為非中文字符,UDC為用戶自定義字符
3.
微軟早在Windows 95簡體中文版中就采用了GBK編碼,也就是對微軟內(nèi)部之前的代碼頁936(即Code Page 936,簡寫為CP936)進(jìn)行了擴展,之前CP936和GB2312-1980幾乎一模一樣。(代碼頁后文有詳細(xì)介紹)
微軟的CP936通常被視為等同于GBK,連IANA(Internet Assigned Numbers Authority互聯(lián)網(wǎng)號碼分配局)也將“CP936”視作“GBK”的別名。
但事實上比較起來,GBK定義的字符較CP936多出了95個(15個非漢字及80個漢字),都是當(dāng)時沒有收入ISO/IEC 10646 (即UCS) / Unicode的字符。(UCS、Unicode后文有詳細(xì)介紹)
?
四、GB18030
1.
中國國家質(zhì)量技術(shù)監(jiān)督局于2000年3月17日推出了GB18030-2000標(biāo)準(zhǔn),以取代GBK。GB18030-2000除保留全部GBK編碼漢字之外,在第二字節(jié)再度進(jìn)行擴展,增加了大約一百個漢字及四位元組編碼空間。
GB18030《信息交換用漢字編碼字符集基本集的補充》是我國繼GB2312-1980和GB13000-1993之后最重要的漢字編碼標(biāo)準(zhǔn),是我國計算機系統(tǒng)必須遵循的基礎(chǔ)性標(biāo)準(zhǔn)之一。
2.
2005年,GB18030編碼方案在GB18030-2000的基礎(chǔ)上又進(jìn)行了擴充,于是又有了GB18030-2005《信息技術(shù)中文編碼字符集》。
如前所述,GB18030-2000是GBK的升級版本,它的主要特點是在GBK基礎(chǔ)上增加了CJK中日韓統(tǒng)一表意文字?jǐn)U充A的漢字;而GB18030-2005的主要特點是在GB18030-2000基礎(chǔ)上又增加了CJK中日韓統(tǒng)一表意文字?jǐn)U充B的漢字。
微軟也為GB18030定義了專門的代碼頁:CP54936,但是這個代碼頁實際上并沒有真正使用(在Windows 7的“控制面板”-“區(qū)域和語言”-“管理”-“非Unicode程序的語言”中沒有提供選項;在Windows cmd命令行中可通過命令chcp 54936更改,之后在cmd中可顯示中文,但卻不支持中文輸入)。
?
五、GB13000
1.
在所有的GB編碼方案中,除了逐步擴展并保持向下兼容的GB2312、GBK、GB18030等GB系列編碼方案,還有一個與GB2312、GBK、GB18030等GB系列編碼方案不兼容的、特殊的GB編碼方案——GB13000編碼方案。(注意,雖然GBK的制定,主要目的就是為了收錄GB13000中的所有字符,但GBK的編碼方式與GB13000是完全不同的。因此,習(xí)慣上所稱的GB系列編碼方案一般并不包括GB13000在內(nèi)。)
為了對世界各個國家和地區(qū)的所有字符進(jìn)行統(tǒng)一編碼,以實現(xiàn)對世界上所有字符在計算機上的統(tǒng)一處理,國際標(biāo)準(zhǔn)化組織制定了新的編碼標(biāo)準(zhǔn)——ISO/IEC 10646標(biāo)準(zhǔn)(即Universal Character Set通用字符集,簡稱UCS,與統(tǒng)一聯(lián)盟制定的Unicode標(biāo)準(zhǔn)兼容,兩者的關(guān)系詳見后文)。
該標(biāo)準(zhǔn)第一次頒布是在1993年,當(dāng)時只頒布了其第一部分,即ISO/IEC 10646.1:1993,除了收錄了世界上其他文字字符之外,其中也收錄了中國大陸、臺灣、日本及韓國的漢字,總共20,902個。
2.
為了與國際標(biāo)準(zhǔn)接軌,中國于是制定了與ISO/IEC 10646.1:1993標(biāo)準(zhǔn)相對應(yīng)的中國國家標(biāo)準(zhǔn)——GB13000.1-1993《信息技術(shù)通用多八位編碼字符集(UCS)第一部分:體系結(jié)構(gòu)與基本多文種平面》。
2010年又發(fā)布了其替代標(biāo)準(zhǔn)——GB13000-2010《信息技術(shù)通用多八位編碼字符集(UCS)》,此標(biāo)準(zhǔn)等同于國際標(biāo)準(zhǔn)ISO/IEC 10646:2003《信息技術(shù)通用多八位編碼字符集(UCS)》。
GB13000與國際標(biāo)準(zhǔn)ISO/IEC10646及Unicode標(biāo)準(zhǔn)目前在基本平面(即BMP,詳見后文)上基本保持一致。
各漢字(中文字符)編碼方案之間的關(guān)系(Big5為繁體漢字編碼方案,主要通行于港澳臺地區(qū),本文不作詳細(xì)介紹)
?
六、CJK中日韓統(tǒng)一表意文字
1.
CJK指的是中日韓統(tǒng)一表意文字(CJK Unified Ideographs),也稱統(tǒng)一漢字(Unihan),目的是要把分別來自中文(包含壯文)、日文、韓文、越文中,起源相同、本義相同、形狀一樣或稍異的表意文字在Unicode標(biāo)準(zhǔn)及ISO/IEC 10646標(biāo)準(zhǔn)內(nèi)賦予相同的碼點值。(Unicode標(biāo)準(zhǔn)及ISO/IEC 10646標(biāo)準(zhǔn)后文有詳細(xì)解釋)
CJK是中文(Chinese)、日文(Japanese)、韓文(Korean)三國文字英文首字母的縮寫。顧名思義,它能夠支持這三種文字,但實際上,CJK能夠支持包括中文(包含壯文)、日文、韓文、越文在內(nèi)的多種亞洲雙字節(jié)文字。
2.
所謂“起源相同、本義相同、形狀一樣或稍異的表意文字”,主要為漢字,包括繁體字、簡體字;但也有仿漢字,包括方塊壯字、日本漢字(漢字/かんじ)、韓國漢字(漢字/??)、越南的喃字(?喃/Ch? N?m)與儒字(?儒/Ch? Nho)等。
此計劃原本只包含中文、日文及韓文中所使用的漢字和仿漢字,統(tǒng)稱中日韓(CJK)統(tǒng)一表意文字(Unified Ideographs)。后來,此計劃才加入了越南文(Vietnamese)的喃字,所以又合稱為中日韓越(CJKV)統(tǒng)一表意文字。
?
七、小結(jié)
1.
GB類字符集均屬于雙字節(jié)字符集DBCS(Double Byte Character Set)。
(注意,這里的“GB類字符集”指的是除了單字節(jié)編碼的ASCII字符之外的部分,因此屬于狹義;嚴(yán)格來講,廣義上的“GB類字符集”包括了單字節(jié)編碼的ASCII字符以及雙字節(jié)編碼的非ASCII字符,因此廣義上的GB類字符集屬于單字節(jié)與雙字節(jié)混合字符集。在一段表述中,具體指的是狹義還是廣義,需根據(jù)上下文而定。)
基于DBCS的編碼方案里,最大的特點是兩字節(jié)長的中文字符和一字節(jié)長的英文字符(ASCII字符)完全兼容,可以并存于同一個文件內(nèi)。
2.
因此,在使用基于DBCS的編碼方案的年代,寫程序時為了支持中文處理,必須要注意字符串里的每一個字節(jié)的值,如果這個值是大于127的,那么就認(rèn)為一個雙字節(jié)字符集里的字符出現(xiàn)了。
使用GB類編碼方案時一般都要時刻記住:一個漢字由兩個字節(jié)組成(即一個漢字占用的存儲空間相當(dāng)于兩個英文字符所占用的存儲空間)。
?
【預(yù)告:下一篇將重點剖析非常容易令人困惑的簡體漢字編碼中的區(qū)位碼、國標(biāo)碼(交換碼)、內(nèi)碼(機內(nèi)碼)、外碼(輸入碼)、字形碼(輸出碼)的區(qū)別及關(guān)系,敬請關(guān)注!】
?
總結(jié)
以上是生活随笔為你收集整理的【转】刨根究底字符编码之五——简体汉字编码方案(GB2312、GBK等)以及全角、半角、CJK的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 所有用户随便用!Adobe宣布网页版Ph
- 下一篇: 今年来范围最大最强高温来袭 河南等可达4