计算机字符集简史
雖然不能確定人類開始講話的時(shí)間,但書寫已有大約6000年的歷史了.實(shí)際上,早期書寫的內(nèi)容是象形文字.每個(gè)字符都對(duì)應(yīng)于發(fā)聲的字母表則出現(xiàn)于大約3000年前.雖然人們過(guò)去使用的多種書寫語(yǔ)言都用得好好的,但19世紀(jì)的幾個(gè)發(fā)明者還是看到了更多的需求.Samuel F. B. Morse在1838年到1854年間發(fā)明了電報(bào),當(dāng)時(shí)他還發(fā)明了一種電報(bào)上使用的代碼.字母表中的每個(gè)字符對(duì)應(yīng)于一系列短的和長(zhǎng)的脈沖(點(diǎn)和破折號(hào)).雖然其中大小寫字母之間沒(méi)有區(qū)別,但數(shù)字和標(biāo)點(diǎn)符號(hào)都有了自己的代碼.
Morse代碼并不是以其它圖畫的或印刷的象形文字來(lái)代表書寫語(yǔ)言的第一個(gè)例子.1821年到1824年之間,年輕的Louis Braille受到在夜間讀寫信息的軍用系統(tǒng)的啟發(fā),發(fā)明了一種代碼,它用紙上突起的點(diǎn)作為代碼來(lái)幫助盲人閱讀.Braille代碼實(shí)際上是一種6位代碼,它把字符、常用字母組合、常用單字和標(biāo)點(diǎn)進(jìn)行編碼.一個(gè)特殊的escape代碼表示后續(xù)的字符代碼應(yīng)解釋為大寫.一個(gè)特殊的shift代碼允許后續(xù)代碼被解釋為數(shù)字.
Telex代碼,包括Baudot (以一個(gè)法國(guó)工程師命名,該工程師死于1903年)以及一種被稱為CCITT #2的代碼(1931年被標(biāo)準(zhǔn)化),都是包括字符和數(shù)字的5位代碼.
美國(guó)標(biāo)準(zhǔn)
早期計(jì)算機(jī)的字符碼是從Hollerith卡片(號(hào)稱不能被折迭、卷曲或毀傷)發(fā)展而來(lái)的,該卡片由Herman Hollerith發(fā)明并首次在1890年的美國(guó)人口普查中使用.6位字符碼系統(tǒng)BCDIC(Binary-Coded Decimal Interchange Code:二進(jìn)制編碼十進(jìn)制交換編碼)源自Hollerith代碼,在60年代逐步擴(kuò)展為8位EBCDIC,并一直是IBM大型主機(jī)的標(biāo)準(zhǔn),但沒(méi)使用在其它地方.
美國(guó)信息交換標(biāo)準(zhǔn)碼(ASCII:American Standard Code for Information Interchange)起始于50年代后期,最后完成于1967年.開發(fā)ASCII的過(guò)程中,在字符長(zhǎng)度是6位、7位還是8位的問(wèn)題上產(chǎn)生了很大的爭(zhēng)議.從可靠性的觀點(diǎn)來(lái)看不應(yīng)使用替換字符,因此ASCII不能是6位編碼,但由于費(fèi)用的原因也排除了8位版本的方案(當(dāng)時(shí)每位的儲(chǔ)存空間成本仍很昂貴).這樣,最終的字符碼就有26個(gè)小寫字母、26個(gè)大寫字母、10個(gè)數(shù)字、32個(gè)符號(hào)、33個(gè)句柄和一個(gè)空格,總共128個(gè)字符碼.ASCII現(xiàn)在記錄在ANSI X3.4-1986字符集-用于信息交換的7位美國(guó)國(guó)家標(biāo)準(zhǔn)碼(7-Bit ASCII:7-Bit American National Standard Code for Information Interchange),由美國(guó)國(guó)家標(biāo)準(zhǔn)協(xié)會(huì)(American National Standards Institute)發(fā)布.圖2-1中所示的ASCII字符碼與ANSI文件中的格式相似.
ASCII有許多優(yōu)點(diǎn).例如,26個(gè)字母代碼是連續(xù)的(在EBCDIC代碼中就不是這樣的);大寫字母和小寫字母可通過(guò)改變一位數(shù)據(jù)而相互轉(zhuǎn)化;10個(gè)數(shù)字的代碼可從數(shù)值本身方便地得到(在BCDIC代碼中,字符'0'的編碼在字符'9'的后面!)
最棒的是,ASCII是一個(gè)非??煽康臉?biāo)準(zhǔn).在鍵盤、視訊顯示卡、系統(tǒng)硬件、打印機(jī)、字體文件、操作系統(tǒng)和Internet上,其它標(biāo)準(zhǔn)都不如ASCII碼流行而且根深蒂固.
國(guó)際方面
ASCII的最大問(wèn)題就是該縮寫的第一個(gè)字母.ASCII是一個(gè)真正的美國(guó)標(biāo)準(zhǔn),所以它不能良好滿足其它講英語(yǔ)國(guó)家的需要.例如英國(guó)的英鎊符號(hào)(£)在哪里?
英語(yǔ)使用拉丁(或羅馬)字母表.在使用拉丁語(yǔ)字母表的書寫語(yǔ)言中,英語(yǔ)中的單詞通常很少需要重音符號(hào)(或讀音符號(hào)).即使那些傳統(tǒng)慣例加上讀音符號(hào)也無(wú)不當(dāng)?shù)挠⒄Z(yǔ)單字,例如c鰋perate或者résumé,拼寫中沒(méi)有讀音符號(hào)也會(huì)被完全接受.
但在美國(guó)以南、以北,以及大西洋地區(qū)的許多國(guó)家,在語(yǔ)言中使用讀音符號(hào)很普遍.這些重音符號(hào)最初是為使拉丁字母表適合這些語(yǔ)言讀音不同的需要.在遠(yuǎn)東或西歐的南部旅游,您會(huì)遇到根本不使用拉丁字母的語(yǔ)言,例如希臘語(yǔ)、希伯來(lái)語(yǔ)、阿拉伯語(yǔ)和俄語(yǔ)(使用斯拉夫字母表).如果您向東走得更遠(yuǎn),就會(huì)發(fā)現(xiàn)中國(guó)象形漢字,日本和朝鮮也采用漢字系統(tǒng).
ASCII的歷史開始于1967年,此后它主要致力于克服其自身限制以更適合于非美國(guó)英語(yǔ)的其它語(yǔ)言.例如,1967年,國(guó)際標(biāo)準(zhǔn)化組織(ISO:International Standards Organization)推薦一個(gè)ASCII的變種,代碼0x40、0x5B、0x5C、0x5D、0x7B、0x7C和0x7D'為國(guó)家使用保留',而代碼0x5E、0x60和0x7E標(biāo)為'當(dāng)國(guó)內(nèi)要求的特殊字符需要8、9或10個(gè)空間位置時(shí),可用于其它圖形符號(hào)'.這顯然不是一個(gè)最佳的國(guó)際解決方案,因?yàn)檫@并不能保證一致性.但這卻顯示了人們?nèi)绾蜗氡M辦法為不同的語(yǔ)言來(lái)編碼的.
擴(kuò)展ASCII
在小型計(jì)算機(jī)開發(fā)的初期,就已經(jīng)嚴(yán)格地建立了8位字節(jié).因此,如果使用一個(gè)字節(jié)來(lái)保存字符,則需要128個(gè)附加的字符來(lái)補(bǔ)充ASCII.1981年,當(dāng)最初的IBM PC推出時(shí),視訊卡的ROM中燒有一個(gè)提供256個(gè)字符的字符集,這也成為IBM標(biāo)準(zhǔn)的一個(gè)重要組成部分.
最初的IBM擴(kuò)展字符集包括某些帶重音的字符和一個(gè)小寫希臘字母表(在數(shù)學(xué)符號(hào)中非常有用),還包括一些塊型和線狀圖形字符.附加的字符也被添加到ASCII控制字符的編碼位置,這是因?yàn)榇蠖鄶?shù)控制字符都不是拿來(lái)顯示用的.
該IBM擴(kuò)展字符集被燒進(jìn)無(wú)數(shù)顯示卡和打印機(jī)的ROM中,并被許多應(yīng)用程序用于修飾其文字模式的顯示方式.不過(guò),該字符集并沒(méi)有為所有使用拉丁字母表的西歐語(yǔ)言提供足夠多的帶重音字符,而且也不適用于Windows.Windows不需要圖形字符,因?yàn)樗幸粋€(gè)完全圖形化的系統(tǒng).
在Windows 1.0(1985年11月發(fā)行)中,Microsoft沒(méi)有完全放棄IBM擴(kuò)展字符集,但它已退居第二重要位置.因?yàn)樽裱薃NSI草案和ISO標(biāo)準(zhǔn),純Windows字符集被稱作'ANSI字符集'.ANSI草案和ISO標(biāo)準(zhǔn)最終成為ANSI/ISO 8859-1-1987,即'American National Standard for Information Processing-8-Bit Single-Byte Coded Graphic Character Sets-Part 1: Latin Alphabet No 1',通常也簡(jiǎn)寫為'Latin 1'.
在Windows 1.0的《Programmer's Reference》中印出了ANSI字符集的最初版本,
空方框表示該位置未定義字符.這與ANSI/ISO 8859-1的最終定義一致.ANSI/ISO 8859-1僅顯示了圖形字符,而沒(méi)有控制字符,因此沒(méi)有定義DEL.此外,代碼0xA0定義為一個(gè)非斷開的空格(這意味著在編排格式時(shí),該字符不用于斷開一行),代碼0xAD是一個(gè)軟連字符(表示除非在行尾斷開單詞時(shí)使用,否則不顯示).此外,ANSI/ISO 8859-1將代碼0xD7定義為乘號(hào)(*),0xF7為除號(hào)(/).Windows中的某些字體也定義了從0x80到0x9F的某些字符,但這些不是ANSI/ISO 8859-1標(biāo)準(zhǔn)的一部分.
MS-DOS 3.3(1987年4月發(fā)行)向IBM PC用戶引進(jìn)了代碼頁(yè)(code page)的概念,Windows也使用此概念.代碼頁(yè)定義了字符的映像代碼.最初的IBM字符集被稱作代碼頁(yè)437,或者'MS-DOS Latin US).代碼頁(yè)850就是'MS-DOS Latin 1',它用附加的帶重音字母(但不是圖2-2所示的Latin 1 ISO/ANSI標(biāo)準(zhǔn))代替了一些線形字符.其它代碼頁(yè)被其它語(yǔ)言定義.最低的128個(gè)代碼總是相同的;較高的128個(gè)代碼取決于定義代碼頁(yè)的語(yǔ)言.
在MS-DOS中,如果用戶為PC的鍵盤、顯示卡和打印機(jī)指定了一個(gè)代碼頁(yè),然后在PC上創(chuàng)建、編輯和打印文件,一切都很正常,每件事都會(huì)保持一致.然而,如果用戶試圖與使用不同代碼頁(yè)的用戶交換文件,或者在機(jī)器上改變代碼頁(yè),就會(huì)產(chǎn)生問(wèn)題.字符碼與錯(cuò)誤的字符相關(guān)聯(lián).應(yīng)用程序能夠?qū)⒋a頁(yè)信息與文件一起保存來(lái)試圖減少問(wèn)題的產(chǎn)生,但該策略包括了某些在代碼頁(yè)間轉(zhuǎn)換的工作.
雖然代碼頁(yè)最初僅提供了不包括帶重音符號(hào)字母的附加拉丁字符集,但最終代碼頁(yè)的較高的128個(gè)字符還是包括了完整的非拉丁字母,例如希伯來(lái)語(yǔ)、希臘語(yǔ)和斯拉夫語(yǔ).自然,如此多樣會(huì)導(dǎo)致代碼頁(yè)變得混亂;如果少數(shù)帶重音的字母未正確顯示,那么整個(gè)文字便會(huì)混亂不堪而不可閱讀.
代碼頁(yè)的擴(kuò)展正是基于所有這些原因,但是還不夠.斯拉夫語(yǔ)的MS-DOS代碼頁(yè)855與斯拉夫語(yǔ)的Windows代碼頁(yè)1251以及斯拉夫語(yǔ)的Macintosh代碼頁(yè)10007不同.每個(gè)環(huán)境下的代碼頁(yè)都是對(duì)該環(huán)境所作的標(biāo)準(zhǔn)字符集修正.IBM OS/2也支援多種EBCDIC代碼頁(yè).
但等一下,你會(huì)發(fā)現(xiàn)事情變得更糟糕.
雙字節(jié)字符集
迄今為止,我們已經(jīng)看到了256個(gè)字符的字符集.但中國(guó)、日本和韓國(guó)的象形文字符號(hào)有大約21,000個(gè).如何容納這些語(yǔ)言而仍保持和ASCII的某種兼容性呢?
解決方案(如果這個(gè)說(shuō)法正確的話)是雙字節(jié)字符集(DBCS:double-byte character set).DBCS從256代碼開始,就像ASCII一樣.與任何行為良好的代碼頁(yè)一樣,最初的128個(gè)代碼是ASCII.然而,較高的128個(gè)代碼中的某些總是跟隨著第二個(gè)字節(jié).這兩個(gè)字節(jié)一起(稱作首字節(jié)和跟隨字節(jié))定義一個(gè)字符,通常是一個(gè)復(fù)雜的象形文字.
雖然中文、日文和韓文共享一些相同的象形文字,但顯然這三種語(yǔ)言是不同的,而且經(jīng)常是同一個(gè)象形文字在三種不同的語(yǔ)言中代表三件不同的事.Windows支持四個(gè)不同的雙字節(jié)字符集:代碼頁(yè)932(日文)、936(簡(jiǎn)體中文)、949(韓語(yǔ))和950(繁體漢字).只有為這些國(guó)家(地區(qū))生產(chǎn)的Windows版本才支持DBCS.
雙字符集問(wèn)題并不是說(shuō)字符由兩個(gè)字節(jié)代表.問(wèn)題在于一些字符(特別是ASCII字符)由1個(gè)字節(jié)表示.這會(huì)引起附加的程序設(shè)計(jì)問(wèn)題.例如,字符串中的字符數(shù)不能由字符串的字節(jié)數(shù)決定.必須剖析字符串來(lái)決定其長(zhǎng)度,而且必須檢查每個(gè)字節(jié)以確定它是否為雙字節(jié)字符的首字節(jié).如果有一個(gè)指向DBCS字符串中間的指針,那么該字符串前一個(gè)字符的地址是什么呢?慣用的解決方案是從開始的指針?lè)治鲈撟址?
Unicode解決方案
我們面臨的基本問(wèn)題是世界上的書寫語(yǔ)言不能簡(jiǎn)單地用256個(gè)8位代碼表示.以前的解決方案包括代碼頁(yè)和DBCS已被證明是不能滿足需要的,而且也是笨拙的.那什么才是真正的解決方案呢?
身為程序?qū)懽髡?我們經(jīng)歷過(guò)這類問(wèn)題.如果事情太多,用8位數(shù)值已經(jīng)不能表示,那么我們就試更寬的值,例如16位值.而且這很有趣的,正是Unicode被制定的原因.與混亂的256個(gè)字符代碼映像,以及含有一些1字節(jié)代碼和一些2字節(jié)代碼的雙字節(jié)字符集不同,Unicode是統(tǒng)一的16位系統(tǒng),這樣就允許表示65,536個(gè)字符.這對(duì)表示所有字符及世界上使用象形文字的語(yǔ)言,包括一系列的數(shù)學(xué)、符號(hào)和貨幣單位符號(hào)的集合來(lái)說(shuō)是充裕的.
明白Unicode和DBCS之間的區(qū)別很重要.Unicode使用(特別在C程序設(shè)計(jì)語(yǔ)言環(huán)境里)'寬字符集'.'Unicode中的每個(gè)字符都是16位寬而不是8位寬.'在Unicode中,沒(méi)有單單使用8位數(shù)值的意義存在.相比之下,在雙字節(jié)字符集中我們?nèi)匀惶幚?位數(shù)值.有些字節(jié)自身定義字符,而某些字節(jié)則顯示需要和另一個(gè)字節(jié)共同定義一個(gè)字符.
處理DBCS字符串非常雜亂,但是處理Unicode文字則像處理有秩序的文字.您也許會(huì)高興地知道前128個(gè)Unicode字符(16位代碼從0x0000到0x007F)就是ASCII字符,而接下來(lái)的128個(gè)Unicode字符(代碼從0x0080到0x00FF)是ISO 8859-1對(duì)ASCII的擴(kuò)展.Unicode中不同部分的字符都同樣基于現(xiàn)有的標(biāo)準(zhǔn).這是為了便于轉(zhuǎn)換.希臘字母表使用從0x0370到0x03FF的代碼,斯拉夫語(yǔ)使用從0x0400到0x04FF的代碼,美國(guó)使用從0x0530到0x058F的代碼,希伯來(lái)語(yǔ)使用從0x0590到0x05FF的代碼.中國(guó)、日本和韓國(guó)的象形文字(總稱為CJK)占用了從0x3000到0x9FFF的代碼.
Unicode的最大好處是這里只有一個(gè)字符集,沒(méi)有一點(diǎn)含糊.Unicode實(shí)際上是個(gè)人計(jì)算機(jī)行業(yè)中幾乎每個(gè)重要公司共同合作的結(jié)果,并且它與ISO 10646-1標(biāo)準(zhǔn)中的代碼是一一對(duì)應(yīng)的.Unicode的重要參考文獻(xiàn)是《The Unicode Standard,Version 2.0》(Addison-Wesley出版社,1996年).這是一本特別的書,它以其它文件少有的方式顯示了世界上書寫語(yǔ)言的豐富性和多樣性.此外,該書還提供了開發(fā)Unicode的基本原理和細(xì)節(jié).
Unicode有缺點(diǎn)嗎?當(dāng)然有.Unicode字符串占用的內(nèi)存是ASCII字符串的兩倍.(然而壓縮文件有助于極大地減少文件所占的磁盤空間.)但也許最糟的缺點(diǎn)是:人們相對(duì)來(lái)說(shuō)還不習(xí)慣使用Unicode.身為程序?qū)懽髡?這就是我們的工作.
總結(jié)
- 上一篇: 关于Unicode字符集(http://
- 下一篇: swift单元测试(三)XCTest之U