編碼字符集、字符編碼
編碼字符集: 表示某種編碼所涉及到字符的集合。例如ASCII字符集、GB2312字符集。僅表示集合,集合元素(即字符)按照某種順序排放,并編上序號。如Unicode。
字符編碼: 把字符集中的字符 編碼為 二進制,用來表示字符集中的字符,是字符集的實現方式。如UTF-8,UTF-16,UTF-32就是Unicode的實現。
一、歐美編碼
發展關系: ASCII -> EASCII -> ISO 8859
ASCII
最初的ASCII只有七位(用于36位計算機),由ANSI協會于1963年公布首版標準。只能支持基礎拉丁字符。
記得 ANSI C 標準嗎?就是這個協會發布的。
注:我們現在通常說到ANSI編碼,通常指的是平臺的默認編碼,例如 英文操作系統中是ISO-8859-1,中文系統是GBK 。
wikipedia:Eventually, as 8-, 16- and 32-bit (and later 64-bit) computers began to replace 18- and 36-bit computers as the norm, it became common to use an 8-bit byte to store each character in memory, providing an opportunity for extended, 8-bit, relatives of ASCII.
而隨著8位、16位、32位開始替代18位和36位計算機,此時ASCII可以從7位擴展到8位,擴展后的ASCII稱為EASCII。
EASCII(Extended ASCII)
EASCII兼容ASCII,在其前面擴展一位。它解決了部份西歐語言的顯示問題。此外還擴充了符號,包括制表符、計算符號、希臘字母和特殊的拉丁符號。
雖然它解決了西歐字符的編碼問題,但是對于歐洲其他地方卻沒有辦法。于是出現了ISO 8859。
ISO 8859
ISO 8859是單字節編碼,兼容ASCII。主要用于歐洲。
它本身不是一個標準,而是一系列標準,由15個字符集所組成。表示為ISO 8850-n (n = 1,2,3 ...11,13...16,沒有12)。
ISO 8859-1 有個別名:Latin-1,是西歐常用字符,包括德法兩國的字母。
其00000000(0×00)-01111111(0x7F)范圍段與ASCII保持一致,
而10000000(0×80)-11111111(0xFF)范圍段被擴展用到不同的字符集。
二、中文編碼
- 兼容關系
GB2312 < GBK < GB18030-2000 < GB18030-2005
- GB2312與BIG5有沖突
- GB2312 有6763個漢字, GBK 有21003個漢字, GB18030-2000 有27533個漢字, GB18030-2005 有70244個漢字。
GB 2312-1980
又簡稱為GB 2312或GB 2312-80。1980為該字符集發布年份。GB為國標(國家標準)拼音首字母。
GB 2312將ASCII里本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這就是常說的”全角”字符,而原來在127號以下的那些就叫”半角”字符。
GBK
GBK中英文都用兩個字節來表示,兼容GB2312,加入對繁體字的支持。K為擴展的Kuo首字母。
windows用CP936來實現對GBK字符集的編解碼。因此有些地方charset=windows-936就是指GBK。
GB 2312的代碼頁為:CP20936
GB 18030-2000
GBK的取代版本,在GBK基礎上增加了CJK統一漢字擴充區A的漢字。
CJK: China Japan Korea,中日韓
GB 18030-2005
在GB 18030-2000的基礎上加上了CJK統一漢字擴充區B的漢字,以及少數民族的文字。
GB 18030與GB 2312-1980完全兼容,與GBK基本兼容,支持GB 13000及Unicode的全部統一漢字,共收錄漢字70244個。
BIG5
與GB2312有沖突。繁體字符集。Big->大寫。
BIG5是使用繁體中文(正體中文)社區中最常用的電腦漢字字符集標準,共收錄13,060個漢字。BIG5雖普及于臺灣、香港與澳門等繁體中文通行區,但長期以來并非當地的國家標準,而只是業界標準。
BIG5-2003
2003年,Big5被收錄到CNS11643中文標準交換碼的附錄當中,取得了較正式的地位。這個最新版本被稱為Big5-2003。
Unicode
盡管人們能夠在一臺計算機上查閱不同語言的文檔,但是一份文檔無法同時使用多種編碼。特別是在網絡上,各個國家互相訪問的時候,會出現亂碼。Unicode就是用來解決這個問題的。
Unicode基于通用字符集(Universal Character Set)的標準來發展,它幾乎涵蓋了各個國家語言可能出現的符號和文字,并為它們編號。
Unicode中文范圍 4E00-9FBF:CJK 統一表意符號。
Unicode就是一開始提到的編碼字符集,而UTF-8、UTF-16、UTF-32就是字符編碼,即Unicode規則字庫的實現形式。
Unicode使用4字節的數字來表達每個字母、符號,或者表意文字。但是這樣有一個問題:如果直接采用4字節的編碼,那么就會浪費大量空間。例如,一個存儲器本來可以存儲800份以ASCII編碼的文檔,現在用Unicode編碼,只能存儲200份,這樣大量的存儲空間就被浪費了。
UTF-8巧妙地解決了這個問題。
UTF-8
UTF-8使用可變長的編碼,例如 ASCII 部分仍然使用一個字節,中文用兩個字節……。也因為如此,它沒有實現所有的 Unicode 的字符,它只實現了Unicode的Plane 0(Unicode共有16個Plane。Plane 0又稱為BMP,Basic Multilingual Plane)。
UTF-8的最小編碼單位為一個字節。一個字節的前1-3個bit為描述性部分,后面為實際序號部分。其編碼規則如下:
- 如果字節以0開頭,則代表當前字符為單字節字符。
- 如果字節以110開頭,則代表當前字符為雙字節字符。其第二個字節以10開頭。
- 如果字節以1110開頭,則代表當前字符為三字節字符。其第二、第三個字節以10開頭。
- 如果字節以10開頭,則代表當前字節為多字節字符(即上面那兩點)的第二或第三個字節。
是不是感覺跟 IP 地址的 A, B, C, D 類的劃分很像?這種分類方式應該可以推廣到很多地方去。
UTF-8與中文:
- GB13000.1-1993 的字符集包含 20902 個漢字。Unicode 標準目前在基本平面上與 GB 13000 保持一致。采納 UTF-16 方案作為未來實現 01H 到 0FH 共15個輔助平面的方式。其它方面與 GB 13000 基本一致。
- UTF-8 與 GBK 的互相轉換是通過查表來實現的。UTF-8 只是 Unicode 的一種實現,當它要轉碼時,要轉換成 Unicode 碼,查 Unicode 表。
關于查表,我去看了 Unicode 表,只有該字符集編碼和對應的中文,并沒有其他編碼的碼值。只有這樣可是沒辦法轉換的啊,因為計算機只能識別0和1。
于是我推測了一下:編碼字符集存儲在數據庫。在數據庫中,一個字符同時存儲了幾種編碼方式所對應的碼。在從 編碼A 轉換為 編碼B 的時候,先在數據庫中根據 編碼A 尋找對應的字符,接著讀取其在 B 中的編碼。
UTF-8 的缺陷是無法表示 Plane 0 外的字符。而UTF-16可以應對這種情況。
UTF-16/UCS-2
UCS = Universal Character Set
UTF-16由UCS-2發展而來。UCS-2最初設計的時候只考慮到BMP(Plane 0)字符,因此使用固定2個字節長度,也就是說,它無法表示Unicode其他層面上的字符,而UTF-16為了解除這個限制,支持Unicode全字符集的編解碼,采用了變長編碼,最少使用2個字節,如果要編碼BMP以外的字符,則需要4個字節結對。
UTF-8和UTF-16的變長是不一樣的。UTF-8以一個字節為單位,擴展時,可以1-> 2-> 3字節;而UTF-16以兩個字節為單位,擴展時只能2-> 4字節。
UTF-32/UCS-4
將UCS-4的BMP去掉前面的兩個零字節就得到了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就得到了UCS-4的BMP。而目前的UCS-4規范中還沒有任何字符被分配在BMP之外。
本來UTF-32是UCS-4的一個子集。但現在它們幾乎完全一樣,不過UTF-32添加了額外的Unicode語義(可以編碼更多的Unicode字符)。
UTF-8 with BOM
BOM的全稱是Byte Order Mark,BOM是微軟給UTF-8編碼加上的,用于標識文件使用的是UTF-8編碼,即在UTF-8編碼的文件起始位置,加入三個字節“EF BB BF”。
這是微軟特有的,Windows 的記事本(即新建文本文檔,txt)就是用UTF-8 with BOM。UTF-8標準并不推薦包含BOM的方式。采用加BOM的UTF-8編碼文件,對于一些只支持標準UTF-8編碼的環境,可能導致問題。比如,網頁第一行可能會顯示一個“?”,明明正確的程序一編譯就報語法錯誤,等等。
既然有如上缺點,為什么還要用BOM呢?因為計算機系統分為大端模式和小端模式。
簡單說就是在處理多字節的時候,可能按照我們的邏輯排列字節,即把數字大的部分放在地址大的部分,數字小的放在地址小的部分,叫做小端模式;也可能反著來,叫做大端模式。
例如對于內存中的數據:e6 84 6c 4e(從左到右地址增大)
大端模式讀取:e6 84 6c 4e
小端模式讀取:4e 6c 84 e6
詳細請看:大小端模式-百度百科
如果同一篇文檔,在大端模式下編寫,傳到小端模式的機器上,就會讀取錯誤。然而只要在文檔的開始,告訴計算機所要讀取的文檔是在大端模式還是小端模式上寫的,就不怕讀取順序出錯了。
參考資料:
- 十分鐘搞清字符集和字符編碼 - 伯樂在線
- 字符集和字符編碼(Charset & Encoding) - 伯樂在線
- 字符編碼常識及問題解析 - 伯樂在線
- 關于字符編碼,你所需要知道的 - 伯樂在線
- 中文字符集編碼Unicode ,gb2312 , cp936 ,GBK,GB18030 - 博客園
- ASCII - Wikipedia
- UTF-16 - Wikipedia
- UTF-32 - Wikipedia
- Byte order mark - Wikipedia
- 程序員趣味讀物:談談Unicode編碼
- 大小端模式-百度百科
- Unicode、GB2312、GBK和GB18030中的漢字
and so on……
文章列表