計算機字符集簡史

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

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