目前計(jì)算機(jī)中用得最廣泛的字符集及其編碼
ASCII咒唆,unicode吧享,utf8艰躺,big5,gb2312礁芦,gbk,gb18030 等
1. ASCII碼
目前計(jì)算機(jī)中用得最廣泛的字符集及其編碼悼尾,是由美國(guó)國(guó)家標(biāo)準(zhǔn)局(ANSI)制定的ASCII碼(American Standard Code for Information Interchange柿扣,美國(guó)標(biāo)準(zhǔn)信息交換碼),它已被國(guó)際標(biāo)準(zhǔn)化組織(ISO)定為國(guó)際標(biāo)準(zhǔn)诀豁,稱為ISO 646標(biāo)準(zhǔn)窄刘。適用于所有拉丁文字字母,ASCII碼有7位碼和8位碼兩種形式舷胜。
我們知道娩践,在計(jì)算機(jī)內(nèi)部,所有的信息最終都表示為一個(gè)二進(jìn)制的字符串烹骨。每一個(gè)二進(jìn)制位(bit)有0和1兩種狀態(tài)翻伺,因此八個(gè)二進(jìn)制位就可以組合出256種狀態(tài),這被稱為一個(gè)字節(jié)(byte)沮焕。也就是說(shuō)吨岭,一個(gè)字節(jié)一共可以用來(lái)表示256種不同的狀態(tài),每一個(gè)狀態(tài)對(duì)應(yīng)一個(gè)符號(hào)峦树,就是256個(gè)符號(hào)辣辫,從 0000000到11111111。
ASCII碼一共規(guī)定了128個(gè)字符的編碼魁巩,比如空格“SPACE”是32(二進(jìn)制00100000)急灭,大寫(xiě)的字母A是65(二進(jìn)制01000001)。這128個(gè)符號(hào)(包括32個(gè)不能打印出來(lái)的控制符號(hào))谷遂,只占用了一個(gè)字節(jié)的后面7位葬馋,最前面的1位統(tǒng)一規(guī)定為0。
注重:在計(jì)算機(jī)的存儲(chǔ)單元 中,一個(gè)ASCII碼值占一個(gè)字節(jié)(8個(gè)二進(jìn)制位)畴嘶,其最高位(b7)用作奇偶校驗(yàn)位蛋逾。所謂奇偶校驗(yàn),是指在代碼傳送過(guò)程中用來(lái)檢驗(yàn)是否出現(xiàn)錯(cuò)誤的一種方 法窗悯,一般分奇校驗(yàn)和偶校驗(yàn)兩種区匣。奇校驗(yàn)規(guī)定:正確的代碼一個(gè)字節(jié)中1的個(gè)數(shù)必須是奇數(shù),若非奇數(shù)蟀瞧,則在最高位b7添1沉颂;偶校驗(yàn)規(guī)定:正確的代碼一個(gè)字節(jié)中 1的個(gè)數(shù)必須是偶數(shù),若非偶數(shù)悦污,則在最高位b7添1铸屉。
2、非ASCII編碼
英語(yǔ)用128個(gè)符號(hào)編碼就夠了切端,但是用來(lái)表示其他語(yǔ)言彻坛,128個(gè)符號(hào)是不夠的。比如踏枣,在法語(yǔ)中昌屉,字母上方有注音符號(hào),它就無(wú)法用ASCII碼表示茵瀑。于是间驮,一些歐洲國(guó)家就決定,利用字節(jié)中閑置的最高位編入新的符號(hào)马昨。比如竞帽,法語(yǔ)中的é的編碼為130(二進(jìn)制10000010)。這樣一來(lái)鸿捧,這些歐洲國(guó)家使用的編碼 體系屹篓,可以表示最多256個(gè)符號(hào)。
但是匙奴,這里又出現(xiàn)了新的問(wèn)題堆巧。不同的國(guó)家有不同的字母,因此泼菌,哪怕它們都使用256個(gè)符號(hào)的編碼方式谍肤,代表的字母卻不一樣。比如哗伯,130在法語(yǔ)編碼中代表了 é谣沸,在希伯來(lái)語(yǔ)編碼中卻代表了字母Gimel (?),在俄語(yǔ)編碼中又會(huì)代表另一個(gè)符號(hào)笋颤。但是不管怎樣,所有這些編碼方式中,0—127表示的符號(hào)是一樣的伴澄,不一樣的只是128—255的這一段赋除。
至于亞洲國(guó)家的文字,使用的符號(hào)就更多了非凌,漢字就多達(dá)10萬(wàn)左右举农。一個(gè)字節(jié)只能表示256種符號(hào),肯定是不夠的敞嗡,就必須使用多個(gè)字節(jié)表達(dá)一個(gè)符號(hào)颁糟。比如,簡(jiǎn)體中文常見(jiàn)的編碼方式是GB2312喉悴,使用兩個(gè)字節(jié)表示一個(gè)漢字棱貌,所以理論上最多可以表示256x256=65536個(gè)符號(hào)。
3箕肃、Unicode的問(wèn)題
正如上一節(jié)所說(shuō)婚脱,世界上存在著多種編碼方式,同一個(gè)二進(jìn)制數(shù)字可以被解釋成不同的符號(hào)勺像。因此障贸,要想打開(kāi)一個(gè)文本文件,就必須知道它的編碼方式吟宦,否則用錯(cuò)誤的編碼方式解讀篮洁,就會(huì)出現(xiàn)亂碼。為什么電子郵件經(jīng)常出現(xiàn)亂碼殃姓?就是因?yàn)榘l(fā)信人和收信人使用的編碼方式不一樣袁波。
可以想象,假如有一種編碼辰狡,將世界上所有的符號(hào)都納入其中锋叨。每一個(gè)符號(hào)都給予一個(gè)獨(dú)一無(wú)二的編碼,那么亂碼問(wèn)題就會(huì)消失宛篇。這就是Unicode娃磺,就像它的名字都表示的,這是一種所有符號(hào)的編碼叫倍。
Unicode當(dāng)然是一個(gè)很大的集合偷卧,現(xiàn)在的規(guī)模可以容納100多萬(wàn)個(gè)符號(hào)吆倦。每個(gè)符號(hào)的編碼都不一樣听诸,比如,U+0639表示阿拉伯字母Ain蚕泽,U+0041表示英語(yǔ)的大寫(xiě)字母A晌梨,U+4E25表示漢字“嚴(yán)”桥嗤。具體的符號(hào)對(duì)應(yīng)表,可以查詢unicode.org仔蝌,或者專門(mén)的漢字對(duì)應(yīng)表泛领。
需要注重的是,Unicode只是一個(gè)符號(hào)集敛惊,它只規(guī)定了符號(hào)的二進(jìn)制代碼渊鞋,卻沒(méi)有規(guī)定這個(gè)二進(jìn)制代碼應(yīng)該如何存儲(chǔ)。
比如瞧挤,漢字“嚴(yán)”的unicode是十六進(jìn)制數(shù)4E25锡宋,轉(zhuǎn)換成二進(jìn)制數(shù)足足有15位(100111000100101),也就是說(shuō)這個(gè)符號(hào)的表示至少需要2個(gè)字節(jié)特恬。表示其他更大的符號(hào)执俩,可能需要3個(gè)字節(jié)或者4個(gè)字節(jié),甚至更多鸵鸥。
這里就有兩個(gè)嚴(yán)重的問(wèn)題奠滑,第一個(gè)問(wèn)題是,如何才能區(qū)別unicode和ascii妒穴?計(jì)算機(jī)怎么知道三個(gè)字節(jié)表示一個(gè)符號(hào)宋税,而不是分別表示三個(gè)符號(hào)呢?第二個(gè) 問(wèn)題是讼油,我們已經(jīng)知道杰赛,英文字母只用一個(gè)字節(jié)表示就夠了,假如unicode統(tǒng)一規(guī)定矮台,每個(gè)符號(hào)用三個(gè)或四個(gè)字節(jié)表示乏屯,那么每個(gè)英文字母前都必然有二到三 個(gè)字節(jié)是0,這對(duì)于存儲(chǔ)來(lái)說(shuō)是極大的浪費(fèi)瘦赫,文本文件的大小會(huì)因此大出二三倍辰晕,這是無(wú)法接受的。
它們?cè)斐傻慕Y(jié)果是:1)出現(xiàn)了unicode的多種存儲(chǔ)方式确虱,也就是說(shuō)有許多種不同的二進(jìn)制格式含友,可以用來(lái)表示unicode。2)unicode在很長(zhǎng)一段時(shí)間內(nèi)無(wú)法推廣校辩,直到互聯(lián)網(wǎng)的出現(xiàn)窘问。
4、UTF-8
互聯(lián)網(wǎng)的普及宜咒,強(qiáng)烈要求出現(xiàn)一種統(tǒng)一的編碼方式惠赫。UTF-8就是在互聯(lián)網(wǎng)上使用最廣的一種unicode的實(shí)現(xiàn)方式。其他實(shí)現(xiàn)方式還包括UTF-16和UTF-32故黑,不過(guò)在互聯(lián)網(wǎng)上基本不用儿咱。反復(fù)一遍庭砍,這里的關(guān)系是,UTF-8是Unicode的實(shí)現(xiàn)方式之一概疆。
UTF-8最大的一個(gè)特點(diǎn)逗威,就是它是一種變長(zhǎng)的編碼方式。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào)岔冀,根據(jù)不同的符號(hào)而變化字節(jié)長(zhǎng)度。
UTF-8的編碼規(guī)則很簡(jiǎn)單概耻,只有二條:
1)對(duì)于單字節(jié)的符號(hào)使套,字節(jié)的第一位設(shè)為0,后面7位為這個(gè)符號(hào)的unicode碼鞠柄。因此對(duì)于英語(yǔ)字母侦高,UTF-8編碼和ASCII碼是相同的。
2)對(duì)于n字節(jié)的符號(hào)(n>1)厌杜,第一個(gè)字節(jié)的前n位都設(shè)為1奉呛,第n+1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10夯尽。剩下的沒(méi)有提及的二進(jìn)制位瞧壮,全部為這個(gè)符號(hào)的unicode碼。
下表總結(jié)了編碼規(guī)則匙握,字母x表示可用編碼的位咆槽。
Unicode符號(hào)范圍 | UTF-8編碼方式
(十六進(jìn)制) | (二進(jìn)制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx (說(shuō)明一下字母占一個(gè)字節(jié))
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx (說(shuō)明一下漢字占兩個(gè)字節(jié))
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
下面,還是以漢字“嚴(yán)”為例圈纺,演示如何實(shí)現(xiàn)UTF-8編碼秦忿。
已 知“嚴(yán)”的unicode是4E25(100111000100101),根據(jù)上表蛾娶,可以發(fā)現(xiàn)4E25處在第三行的范圍內(nèi)(0000 0800-0000 FFFF)灯谣,因此“嚴(yán)”的UTF-8編碼需要三個(gè)字節(jié),即格式是“1110xxxx 10xxxxxx 10xxxxxx”蛔琅。然后胎许,從“嚴(yán)”的最后一個(gè)二進(jìn)制位開(kāi)始,依次從后向前填入格式中的x揍愁,多出的位補(bǔ)0呐萨。這樣就得到了,“嚴(yán)”的UTF-8編碼是 “11100100 10111000 10100101”莽囤,轉(zhuǎn)換成十六進(jìn)制就是E4B8A5谬擦。
5、 Unicode與UTF-8之間的轉(zhuǎn)換
通過(guò)上一節(jié)的例子朽缎,可以看到“嚴(yán)”的Unicode碼是4E25惨远,UTF-8編碼是E4B8A5谜悟,兩者是不一樣的。它們之間的轉(zhuǎn)換可以通過(guò)程序?qū)崿F(xiàn)北秽。
在Windows平臺(tái)下葡幸,有一個(gè)最簡(jiǎn)單的轉(zhuǎn)化方法,就是使用內(nèi)置的記事本小程序Notepad.exe贺氓。打開(kāi)文件后蔚叨,點(diǎn)擊“文件”菜單中的“另存為”命令,會(huì)跳出一個(gè)對(duì)話框辙培,在最底部有一個(gè)“編碼”的下拉條蔑水。
里面有四個(gè)選項(xiàng):ANSI,Unicode扬蕊,Unicode big endian 和 UTF-8搀别。
1)ANSI是默認(rèn)的編碼方式。對(duì)于英文文件是ASCII編碼尾抑,對(duì)于簡(jiǎn)體中文文件是GB2312編碼(只針對(duì)Windows簡(jiǎn)體中文版歇父,假如是繁體中文版會(huì)采用Big5碼)。
2)Unicode編碼指的是UCS-2編碼方式再愈,即直接用兩個(gè)字節(jié)存入字符的Unicode碼榜苫。這個(gè)選項(xiàng)用的little endian格式。
3)Unicode big endian編碼與上一個(gè)選項(xiàng)相對(duì)應(yīng)践磅。我在下一節(jié)會(huì)解釋little endian和big endian的涵義单刁。
4)UTF-8編碼,也就是上一節(jié)談到的編碼方法府适。
選擇完”編碼方式“后羔飞,點(diǎn)擊”保存“按鈕,文件的編碼方式就連忙轉(zhuǎn)換好了檐春。
6逻淌、 Little endian和Big endian
上一節(jié)已經(jīng)提到,Unicode碼可以采用UCS-2格式直接存儲(chǔ)疟暖。以漢字”嚴(yán)“為例卡儒,Unicode碼是4E25,需要用兩個(gè)字節(jié)存儲(chǔ)俐巴,一個(gè)字節(jié)是4E骨望, 另一個(gè)字節(jié)是25。存儲(chǔ)的時(shí)候欣舵,4E在前擎鸠,25在后,就是Big endian方式缘圈;25在前劣光,4E在后袜蚕,就是Little endian方式。
這兩個(gè)古怪的名稱來(lái)自英國(guó)作家斯威夫特的《格列佛游記》绢涡。在該書(shū)中牲剃,小人國(guó)里爆發(fā)了內(nèi)戰(zhàn),戰(zhàn)爭(zhēng)起因是人們爭(zhēng)論雄可,吃雞蛋時(shí)究竟是從大頭(Big- Endian)敲開(kāi)還是從小頭(Little-Endian)敲開(kāi)凿傅。為了這件事情,前后爆發(fā)了六次戰(zhàn)爭(zhēng)滞项,一個(gè)皇帝送了命狭归,另一個(gè)皇帝丟了王位。
因此文判,第一個(gè)字節(jié)在前,就是”大頭方式“(Big endian)室梅,第二個(gè)字節(jié)在前就是”小頭方式“(Little endian)戏仓。
那么很自然的,就會(huì)出現(xiàn)一個(gè)問(wèn)題:計(jì)算機(jī)怎么知道某一個(gè)文件到底采用哪一種方式編碼亡鼠?
Unicode規(guī)范中定義赏殃,每一個(gè)文件的最前面分別加入一個(gè)表示編碼順序的字符,這個(gè)字符的名字叫做”零寬度非換行空格“(ZERO WIDTH NO-BREAK SPACE)间涵,用FEFF表示仁热。這正好是兩個(gè)字節(jié),而且FF比FE大1勾哩。
假如一個(gè)文本文件的頭兩個(gè)字節(jié)是FE FF抗蠢,就表示該文件采用大頭方式;假如頭兩個(gè)字節(jié)是FF FE思劳,就表示該文件采用小頭方式迅矛。
7、ASCII,UNICODE,UTF-8實(shí)例
下面潜叛,舉一個(gè)實(shí)例秽褒。
打開(kāi)”記事本“程序Notepad.exe,新建一個(gè)文本文件威兜,內(nèi)容就是一個(gè)”嚴(yán)“字销斟,依次采用ANSI,Unicode椒舵,Unicode big endian 和 UTF-8編碼方式保存蚂踊。
然后,用文本編輯軟件UltraEdit中的”十六進(jìn)制功能“逮栅,觀察該文件的內(nèi)部編碼方式悴势。
1)ANSI:文件的編碼就是兩個(gè)字節(jié)“D1 CF”窗宇,這正是“嚴(yán)”的GB2312編碼,這也暗示GB2312是采用大頭方式存儲(chǔ)的特纤。
2)Unicode:編碼是四個(gè)字節(jié)“FF FE 25 4E”军俊,其中“FF FE”表明是小頭方式存儲(chǔ),真正的編碼是4E25捧存。
3)Unicode big endian:編碼是四個(gè)字節(jié)“FE FF 4E 25”粪躬,其中“FE FF”表明是大頭方式存儲(chǔ)。
4)UTF-8:編碼是六個(gè)字節(jié)“EF BB BF E4 B8 A5”昔穴,前三個(gè)字節(jié)“EF BB BF”表示這是UTF-8編碼镰官,后三個(gè)“E4B8A5”就是“嚴(yán)”的具體編碼,它的存儲(chǔ)順序與編碼順序是一致的吗货。
8泳唠、GB2312,Big5,GBK,GB18030
字符必須編碼后才能被計(jì)算機(jī)處理。計(jì)算機(jī)使用的缺省編碼方式就是計(jì)算機(jī)的內(nèi)碼宙搬。早期的計(jì)算機(jī)使用7位的ASCII編碼笨腥,為了處理漢字,程序員設(shè)計(jì)了用于簡(jiǎn)體中文的GB2312和用于繁體中文的big5勇垛。
GB2312(1980年)一共收錄了7445個(gè)字符脖母,包括6763個(gè)漢字和682個(gè)其它符號(hào)。漢字區(qū)的內(nèi)碼范圍高字節(jié)從B0-F7闲孤,低字節(jié)從A1-FE谆级,占用的碼位是72*94=6768。其中有5個(gè)空位是D7FA-D7FE讼积。
GB2312支持的漢字太少肥照。1995年的漢字?jǐn)U展規(guī)范GBK1.0收錄了21886個(gè)符號(hào),它分為漢字區(qū)和圖形符號(hào)區(qū)币砂。漢字區(qū)包括21003個(gè)字符建峭。
從 ASCII、GB2312到GBK决摧,這些編碼方法是向下兼容的亿蒸,即同一個(gè)字符在這些方案中總是有相同的編碼,后面的標(biāo)準(zhǔn)支持更多的字符掌桩。在這些編碼中边锁,英 文和中文可以統(tǒng)一地處理。區(qū)分中文編碼的方法是高字節(jié)的最高位不為0波岛。按照程序員的稱呼茅坛,GB2312、GBK都屬于雙字節(jié)字符集 (DBCS)。
2000年 的GB18030是取代GBK1.0的正式國(guó)家標(biāo)準(zhǔn)贡蓖。該標(biāo)準(zhǔn)收錄了27484個(gè)漢字曹鸠,同時(shí)還收錄了藏文、蒙文斥铺、維吾爾文等主要的少數(shù)民族文字彻桃。從漢字字匯 上說(shuō),GB18030在GB13000.1的20902個(gè)漢字的基礎(chǔ)上增加了CJK擴(kuò)展A的6582個(gè)漢字(Unicode碼 0x3400-0x4db5)晾蜘,一共收錄了27484個(gè)漢字邻眷。
CJK就是中日韓的意思。Unicode為了節(jié)省碼位剔交,將中日韓三國(guó)語(yǔ)言中的文字統(tǒng)一編碼肆饶。GB13000.1就是ISO/IEC 10646-1的中文版,相當(dāng)于Unicode 1.1岖常。
GB18030的 編碼采用單字節(jié)驯镊、雙字節(jié)和4字節(jié)方案。其中單字節(jié)竭鞍、雙字節(jié)和GBK是完全兼容的阿宅。4字節(jié)編碼的碼位就是收錄了CJK擴(kuò)展A的6582個(gè)漢字。例如:UCS 的0x3400在GB18030中的編碼應(yīng)該是8139EF30笼蛛,UCS的0x3401在GB18030中的編碼應(yīng)該是8139EF31。
微軟提供了GB18030的升級(jí)包蛉鹿,但這個(gè)升級(jí)包只是提供了一套支持CJK擴(kuò)展A的6582個(gè)漢字的新字體:新宋體-18030滨砍,并不改變內(nèi)碼。Windows 的內(nèi)碼仍然是GBK妖异。
也就是說(shuō)Big5支持繁體中文惋戏,GB2312支持簡(jiǎn)體中文,Big5,GB2312是GBK的子集他膳,GBK是GB18030的子集
9响逢、使用UTF-8與GBK的選擇
GBK是中國(guó)國(guó)家編碼,通用性比UTF8差棕孙,不過(guò)UTF8占用的空間比GBK大.
UTF8是國(guó)際編碼舔亭,它的通用性比較好,外國(guó)人也可以瀏覽論壇蟀俊,而且中文可以直接識(shí)別钦铺,假如你的論壇要做的比較國(guó)際化那就必須用UTF8的