天天看點

【程式設計基礎】—字元編碼之二三事

相信大家在寫腳本或者平時的測試過程中肯定都碰到過亂碼,面對自己不認識的怪異字元,肯定會不知所措。今天這篇文章就帶大家看看編碼格式的發展曆程,讓你碰到問題時有思路可循。

編碼格式發展史

ASCII

衆所周知,世界上第一台計算機是美國人在20世紀40年代發明的,當時确定計算機以二進制(0101)的方式來存儲資料,也就是說能在計算機上顯示的所有字元:數字、大小寫字母、符号等最終都需要轉成計算機可識别的二進制。是以,必須建立一套從字元到二進制的對應關系,于是 美國國家标準協會(American National Standard Institution) 就收集了當時美國所使用的所有字元(共128個)。因為一個位元組包含8位,共有256種二進制組合(2的8次方),是以單個位元組就能覆寫所有的字元,并且單個位元組的最高位也用不上,因為後7位就可以表達128個字元。ASCII表于1967年正式釋出,共包括33個控制字元和95個可顯示字元 。

0000 0000-0001 1111 共33種狀态表示特殊的終端控制(例如列印機響鈴)(0-33)              0011 0000-0011 1010 共10個表示0-9十個數字              0100 0001-0101 1010 共26個表示大寫字母              0110 0001-0111 1010 共26個表示小寫字母              外加33個符号(運算符、特殊符号)              一共128個占7位 高位不用直接補0。
           

上面引入了一些基礎概念,我們簡單介紹下:

  • 位(bit):計算機中最小機關,用二進制的0/1表示。
  • **位元組(byte):**每8位組成一個位元組。
  • **字元:**我們平時可見的文字、字母、符号、數字等。
  • **字元集:**多個字元的集合。
  • **編碼(encode):**将字元轉換成計算機可識别的二進制代碼(0/1代碼)。
  • **解碼(decode):**将計算機表示的0/1編碼轉換成肉眼可見的字元。

EASCII

随後,計算機傳入歐洲,歐洲人發現ASCII無法展示他們自己特有的一些字元(表格符号、計算符号、希臘字母和特殊的拉丁符号)。歐洲人靈光一現:ASCII不是沒有用到最高位嘛,正好可以利用起來,于是他們将ASCII編碼的高位從0變為1,擴充出128個二進制數(10000000~11111111)。

但是實際使用過程中,由于不同國家的字元略有不同,是以有可能同一個二進制數字,但是代表的字元卻是不同的, 比如,1000 0010在法語編碼中代表了é,在希伯來語編碼中卻代表了字母Gimel (?),在俄語編碼中又會代表另一個符号 。不過編碼的0-127是和ASCII完全一緻的,唯一有差別的是後面128-255之間的字元不同。這就是EASCII,它完全相容ASCII。

GB2312

再往後,計算機被引入到亞洲,中華文化博大精深,漢字共包含了古文、現代文字等近十萬個文字,就算隻考慮我們常用字也有6000多個漢字,是以ASCII肯定是沒辦法滿足需求了。于是,在1981年,國家标準化管理委員會正式制定了 中華人民共和國國家标準簡體中文字元集 ,被稱之為GB2312。

它共包含7445個字元,6763個漢字和682個其他字元(拉丁字母、希臘字母、日文平假名及片假名字母、俄語西裡爾字母) ,每個漢字及符号都用兩個位元組來存儲。

BIG5

GB2312是簡體中文字元集,但是中國的港澳台同胞們使用的卻是繁體字,于是在1984年,中國又聯合部分台灣的廠商,一起推出了BIG5編碼,它共收錄13,060個漢字及441個符号,也采用兩個位元組來存儲字元。

Unicode

随着計算機的普及和發展,越來越多的國家希望自己的文字可以顯示在計算機上,于是他們就開始制定自己的編碼格式。但是這樣帶來的後果是,在自己國家電腦上寫的好好的一份檔案,copy到其他國家的電腦上就完全變成亂碼,這挺可怕的,每個國家都活在自己的小世界裡,沒辦法跟其他國家的人交流。

于是國際标準化組織(ISO)及國際電工委員會(IEC)于1984年聯合成立了ISO/IEC小組,核心目的是開發一套統一的編碼格式。1991年,推出了Unicode1.0,不過它并沒有包含 CJK字元(即中日韓) ,可能是因為亞洲這幾個國家的編碼太複雜了。

ISO/IEC 8859

還記得上面我們提到ESCAII時講過,歐洲國家在使用ESCAII時會出現,在128-255之間表示不同國家字元時會略有不同。ISO/IEC小組在1984年成立後的第三年(即1987年)開始啟動ISO 8859标準的編寫,ISO 8859是一系列單位元組字元集的标準,采用了ESAII的部分編碼,主要是為世界各地的不同語言(除中日韓)而單獨編寫的字元集,一共定義了15個字元集:從ISO 8859-1 到ISO 8859-16,需要注意的是沒有ISO 8859-12, 據說-12号本來是預留給印度天城體梵文的,但後來卻不了了之 。

比較常用的是ISO 8859-1,有些環境也稱之為Latin-1,某些軟體,比如mysql的預設編碼格式就是Latin-1。

UCS

UCS( Universal Character Set  通用字元集)是一個超級大的字元集,它包含了已知的所有字元,并且它為每一個字元都配置設定一個唯一的代碼。這其實保證了UCS與其他字元的雙向相容,即将任何編碼格式的文本轉換成UCS,然後再翻譯回原編碼,不會丢失任何資訊。

UCS有兩種編碼方案:UCS-2和UCS-4,UCS-2使用兩個位元組編碼(Unicode預設以UCS-2編碼),UCS-4使用四個位元組編碼。UCS-2其實可以容納的字元數為65536(2的16次方),而UCS-4可以容納的字元數為2147483648(2的31次方)。其實對于UCS-2已經是完全夠用了,基本可以包含世界所有國家的常用文字,如果需要考慮一些偏僻字,那麼UCS-4則絕對可以滿足了。

有的人可能有疑問,為啥有了Unicode還會有UCS,其實UCS是ISO/IEC推出的一種編碼方式,而Unicode起初是美國的一些大公司聯盟為了對抗UCS而推出的,後來兩個組織發現,他們做的大部分事情都是重複的,幹脆握手言和吧,于是後面就聯手釋出Unicode的後續版本,不過UCS也作為單獨的版本釋出過。

UTF

随着計算機網絡的發展,Unicode如何在網絡上傳輸也是必須考慮的問題,因為Unicode采用兩個位元組編碼,如果用Unicode去表示一個ASCII,那麼其第一個位元組就始終為0(因為ASCII隻需要一個位元組)。這就造成了較大的空間浪費,于是UTF系列的編碼應運而生,其最大特别是可變位元組編碼,這樣可以節省帶寬,提高網絡傳輸效率。

UTF-8: 使用1~4個位元組編碼,其中ASCII用1個位元組編碼、 拉丁文、希臘文 等用2個位元組編碼、大部分國家的常用字用3個位元組編碼、其他極少使用的生僻字用4個位元組編碼。

UTF-16: 使用2個或4個位元組編碼,其中ASCII用2個位元組編碼、其他字元使用四個位元組編碼

UTF-32:  等同于UCS-4,對于所有字元都使用四個位元組來編碼

GB13000

前面提到1993年,ISO/IEC組織推出了Unicode1.0,不包含中日韓語言,但是緊接着ISO/IEC就推出了Unicode1.1版本,支援了中日韓語言。中國的标準組織考慮到自己也得有一個字元集,能夠走向世界,于是将Unicode1.1中所有的内容全部搬過來,然後又經過部分修訂完善,釋出了GB130000。

GBK

GBK(K其實是拼音Kuo Zhan的首字母)是對漢字編碼的擴充,這個微軟指定的編碼格式。随着計算機在中國的普及,微軟意識到中國是一個巨大的市場,但是微軟的系統在中國布局,肯定要面對編碼相容性問題,之前的GB2312基本滿足了漢字的處理需求, 但對于人名、古漢語等方面出現的罕用字和繁體字,GB2312不能處理 。是以微軟就利用GB2312中未被利用的編碼空間,收錄了GB130000中所有的字元,制定了GBK編碼(還是兩個位元組),是以GBK是完全相容G2312編碼的。

GB18030

雖然GBK和GB130000編碼已經包含了大部分的漢字和繁體字,但是并沒有考慮到中國的少數民族的語言(中國有56個民族,12個民族有自己的語言)。在2000年,中國标準化組織又起草了GB18030标準,它參考UTF-8的編碼方式,采用多編碼方式(1或2或4個位元組進行編碼)。在2005年,釋出GB18030-2005,共包含70244個漢字 。

ANSI

其實ANSI并不是一種特定的編碼格式,是隻存在于windows上的一種編碼,猜測可能是微軟為了能統一顯示不同國家作業系統的編碼而推出的。比如在在簡體中文Windows作業系統中,ANSI 編碼代表 GBK 編碼;在繁體中文Windows作業系統中,ANSI編碼代表Big5;在日文Windows作業系統中,ANSI 編碼代表 Shift_JIS 編碼 ,在美國的windows作業系統中,就代表ASCII。windows主要通過 code page 來區分不同的編碼格式,你可以在windows cmd視窗通過chcp指令切換code page。

總結

在平時的工作當中,如果碰到亂碼,不要驚慌,隻需要分析檔案的編碼格式、代碼中對編碼的處理方式等等(具體問題還得具體分析),在之後的文章中,牽扯到具體的問題,我們再具體分析。

繼續閱讀