计算机编码总结
英文字母:
字節數 : 1;編碼:GB2312
字節數 : 1;編碼:GBK
字節數 : 1;編碼:GB18030
字節數 : 1;編碼:ISO-8859-1
字節數 : 1;編碼:UTF-8
字節數 : 4;編碼:UTF-16
字節數 : 2;編碼:UTF-16BE
字節數 : 2;編碼:UTF-16LE
?
中文漢字:
字節數 : 2;編碼:GBK
字節數 : 2;編碼:GB18030
字節數 : 1;編碼:ISO-8859-1
字節數 : 3;編碼:UTF-8
字節數 : 4;編碼:UTF-16
字節數 : 2;編碼:UTF-16BE
字節數 : 2;編碼:UTF-16LE
?
編碼發展歷史簡介
第一階段 ASCII
在計算機中,所有的數據只可能是0或者1(用高電平和低電平分別表示1和0),那么我們通常看到的字符也就只能用0和1來表示呀。于是科學家們(這里指的是美國的科學家)就想出一個辦法,把一個特定的數字對應一個特定的字母進行存儲和傳輸,比如我需要存儲字母a,那么我存入一個數字97(即在計算機中存入二進制(01100001),這個過程叫做編碼(encode),而我們在讀取數據的時候,當遇到97時,我們就讓計算機顯示字母a,這個過程叫做解碼(decode)。
為了大家在數據傳輸的時候不至于產生誤會,那么我們需要讓所有的人都使用數字97來代表字母a,所以需要制定一份標準(即碼表),最開始的這個標準叫做ASCII碼表。
規則
- 所有的控制字符(比如CR回車、DEL刪除等)編碼在0-31范圍以及127中。
- 把所有的標點符號,英文大小寫全部放在32-126范圍中。
- 防止以后出現需要補充的情況,把128-255位這么多位置留出來,應該足夠用了吧!所以設置一個字節8位二進制,把這個標準叫American Standard Code for Information Interchange(美國標準信息交換代碼,簡寫為ASCII),標準制定結束。
等等,我們的中文字呢?
美國的"磚家"沒有考慮那么久遠呢!這就是后面出現那么多問題的根源所在啊。
實現方式
第一位始終未0,后面7位表示0-127的范圍,一個數字對應一個字母或者標點符號,亦或者控制符號,即所有的ASCII碼的統一形式為0xxxx xxxx。
第二階段 GB2312,GBK, BIG5 Latin1, ISO-8859-1, JIS, ANSI...
計算機技術到了歐洲,歐洲人發現怎么我們的那么多符號沒有編進去啊!
所以歐洲"磚家"坐到了一起,開始討論。
發現既然美國人把第一位流出來了,那么我們就用128-255的位置好了。
規則
128-159之間為控制字符,160-255位文字符號,其中包括了西歐語言、希臘語、泰語、阿拉伯語、希伯來語。
剛好把美國人給的空間全部用完,世界真美好,謝謝美利堅預留的每一個位置。
磚家們決定把他們的編碼名稱叫做Latin1,后面由于歐洲統一制定ISO標準,所以又有了一個ISO的名稱,即ISO-8859-1。
實現方式
- 0-127的所有位置不動,那么可以兼容ASCII,二進制位0xxx xxxx
- 128-255位置全部用完,二進制位1xxx xxxx
由于所有的位置全部用完,而歐元符號實在指定標準之后才出現的,所以在這個碼表中連歐洲人自己的貨幣符號都沒有辦法放進去。
計算機技術當然也傳到了亞洲大地,比如中國。
中國磚家們坐在一起發現,美國人搞的這個東西真的有問題,預留才128-255的空間,可是我們的漢字個數遠遠超出了這個數目啊,怎么辦??
后面聰明的中國磚家們發現,只能使用2個字節了,否則真的搞不定。
由于必須和美國原來制定的ASCII不沖突,所以指定了如下規則
規則
- 如果一個字節中第一位為0,那么這就是一個ASCII字符。
- 如果一個字節中第一位為1,那么這個是漢字,認定需要2個字節才表示一個編碼的文字。
把這個碼表叫GB2312
這個碼表中包含漢字6763個和非漢字圖形字符682個。
還有很多的空間沒有用到,索性全部預留了吧。
實現方式 - 0xxxxxxx:表示為ASCII字符
-1xxxxxxx 1xxxxxxx:表示為漢字
后來,中國磚家們發現,很多的不常用漢字沒有在碼表中,于是添加了很多的漢字進去,這個編碼叫做GBK,實現方式和GB2312是完全一樣的,兼容GB2312,當然也兼容ASCII。
實現方式
- 0xxxxxxx:表示為ASCII字符
-1xxxxxxx xxxxxxxx:表示為漢字
后面再次添加更多的字符進去,再次命名為GB18030,兼容GBK。由于漢字很多,2個字節并不能完全包括進去,所以GB18030采用2\4位混編的形式。
當然計算機也傳到了日本(JIS)、韓國、臺灣(BIG5)等等地方,大家全部發揮自己的聰明才智,各自實現了自己的編碼。這些編碼都與ASCII兼容,但是相互之間不兼容。
使用 2 個字節來代表一個字符的各種漢字延伸編碼方式,稱為 ANSI 編碼,又稱為"MBCS(Muilti-Bytes Charecter Set,多字節字符集)"。在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼,所以在中文 windows下要轉碼成gb2312,gbk只需要把文本保存為ANSI編碼即可。 不同ANSI編碼之間互不兼容
第三階段
隨著通訊越來越多,而老美發現在自己公司需要國際化的時候,自己原來埋的這個雷真的害了自己。
于是乎,開始研討把世界上幾乎所有文字全部放在一個碼表中,而這個包羅萬象的碼表就叫做Unicode,即萬國碼。
Unicode是國際組織制定的可以容納世界上所有文字和符號的字符編碼方案。Unicode用數字0-0x10FFFF來映射這些字符,最多可以容納1114112個字符,或者說有1114112個碼位。碼位就是可以分配給字符的數字。
實際上,在軟件制造商的協會(unicode.org)在做這個工作時,國際標準化組織(ISO)在做同樣的事情,最后大家都意識到世界上并不需要兩個不同的萬國碼,于是大家坐在一起合并研究的成果,最后的結果就是現在的Unicode。
各個編碼及其范圍
ASCII
編碼范圍00-7F,其中00-1F、FF為控制字符。其它為英文字母、數字、標點符號。
Latin1
編碼范圍00-FF,其中00-7F同ASCII,80-9F為控制符、9F-FF為字母和標點符號.
CP1252
微軟的企業標準,補充了一些符號和歐元符號,為Latin1的超集。
GB2312
編碼范圍為A1A1-F7FE(剔除xx7F),共23940個碼位。其中很多區間沒有用到,而漢字使用的區間為B0A1-F7FE,其他為標點符號和特殊字符。
除常用簡體漢字字符外還包括希臘字母、日文平假名及片假名字母、俄語西里爾字母等字符,未收錄繁體中文漢字和一些生僻字。
對漢字進行了分區管理,其中第一個字節為區位碼,包括下面區位。
01-09區為特殊符號。
16-55區為一級漢字,按拼音排序。
56-87區為二級漢字,按部首/筆畫排序。
10-15區及88-94區則未有編碼。
第二個字節為位字節,01-94總計94個。
為什么實際選擇不是01-5E,而是選擇A1-F7的位置呢?
因為英文可見字符區間為20-7F,加上128(也就是最高位為1)后得到的取件即是A1-FE
區位碼使用了0xA1-0xF7(把01-87區的區號加上0xA0),位字節使用了0xA1-0xFE(把01-94加上 0xA0)
GBK
編碼范圍為8140-FEFE,兼容GB2312,仍然有部分區間沒有用到。
GBK也支持希臘字母、日文假名字母、俄語字母等字符,但不支持韓語中的表音字符(非漢字字符)。GBK還收錄了GB2312不包含的 漢字部首符號、豎排標點符號等字符。
CP936
CP936是微軟指定的標準,屬于企業標準,和GBK的有些許差別,絕大多數情況下可以把CP936當作GBK的別名。
BIG5
Big5是雙字節編碼,高字節編碼范圍是0x81-0xFE,低字節編碼范圍是0x40-0x7E和0xA1-0xFE。和GBK相比,少了低字節是0x80-0xA0的組合。0x8140-0xA0FE是保留區域,用于用戶造字區。
Big5收錄的漢字只包括繁體漢字,不包括簡體漢字,一些生僻的漢字也沒有收錄。
CP950
微軟的企業標準,可以理解為是對 Big5的擴展。
GB18030
編碼范圍同GBK,補充了更多的字符,由于Unicode開始流行且GB18030補充的字符都比較生僻,所以實際使用上基本是GBK。
GB18030編碼是變長編碼,有單字節、雙字節和四字節三種方式。GB18030的單字節編碼范圍是0x00-0x7F,完全等同與ASCII;雙字節編碼的范圍和GBK相同,高字節是0x81-0xFE,低字節的編 碼范圍是0x40-0x7E和0x80-FE;四字節編碼中第一、三字節的編碼范圍是0x81-0xFE,二、四字節是0x30-0x39。
Unicode
中文的編碼范圍為4E00-9FCF,其中9FC4-9FCF之間的區間沒有使用。
一個蛋疼的問題就是這個區間全部都是文字,中文標點沒有包含在其中,中文標點散落在各個位置。詳細請看http://blog.chinaunix.net/uid-12348673-id-3335307.html。
一些特殊的文字和中文部首以及一些特殊符號也不在此范圍內,詳細情況可以參考網址:http://www.cnblogs.com/sosoft/p/3456631.html
編碼方面的一些概念
大尾(big endian)和小尾(little endian)
大尾和小尾是CPU處理多字節數的不同方式。例如“漢”字的Unicode編碼是6C49。那么寫到文件里時,究竟是將6C寫在前面,還是將49寫在前面?如果將6C寫在前面,就是big endian。還是將49寫在前面,就是little endian。
BOM
UTF-8以字節為編碼單元,沒有字節序的問題。UTF-16以兩個字節為編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每個編碼單元的字節序。例如收到一個“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節流“594E”,那么這是“奎”還是“乙”?
Unicode規范中推薦的標記字節順序的方法是BOM,即Byte Order Mark。BOM是一個有點小聰明的想法:
在UCS編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中。UCS規范建議我們在傳輸字節流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。
這樣如果接收者收到FEFF,就表明這個字節流是Big-Endian的;如果收到FFFE,就表明這個字節流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。
UTF-8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗證一下)。所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。
Unicode的實現方式
Unicode只是進行了編碼,也就是說只是一個碼表,至于具體怎么實現,并沒有規定。
下面是Unicode的幾種實現方法。
UTF-8
| 0x0000~0x007F (0 ~ 127) | 1字節 | 0xxxxxxx |
| 0x0080~0x07FF(128 ~ 2047) | 2字節 | 110xxxxx 10xxxxxx |
| 0x0800~FFFF(2048 ~ 65535) | 3字節 | 1110xxxx 10xxxxxx 10xxxxxx |
| 0x10000~1FFFFFF(65536 ~ 2097152) | 4字節 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
| 0x2000000~0x3FFFFFF | 5字節 | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
| 0x4000000~0x7FFFFFFF) | 6字節 | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
理論上說,UTF-8并沒有大小尾的困擾,所以并不需要BOM。
但是一些Windows應用會指定大小尾,比如Notepad,而且Excel在沒有指定BOM的UTF-8文件進行讀取時會使用Windows的codepage,從而出現錯誤。
UTF-16
在Unicode基本多文種平面定義的字符(無論是拉丁字母、漢字或其他文字或符號),一律使用2字節儲存。而在輔助平面定義的字符,會以代理對(surrogate pair)的形式,以兩個2字節的值來儲存。
UTF-16比起UTF-8,好處在于大部分字符都以固定長度的字節 (2字節) 儲存,但UTF-16卻無法兼容于ASCII編碼。
可以認為UTF-16是下面介紹的UCS-2的父集。在沒有輔助平面字符(surrogate code points)前,UTF-16與UCS-2所指的是同一的意思。但當引入輔助平面字符后,就稱為UTF-16了。現在若有軟件聲稱自己支援UCS-2編碼,那其實是暗指它不能支援在UTF-16中超過2bytes的字集。對于小于0x10000的UCS碼,UTF-16編碼就等于UCS碼。
如果一個UTF-16文件沒有指定BOM,默認應該是UTF-16BE,但是在Intel x86中卻是UTF-16LE。所以在現實世界中有很多的沒有指定大小尾的UTF-16卻是UTF-16LE。
UTF-32
每一個Unicode碼位使用恰好32位元。可以粗暴的認為UTF-32和下面要介紹的UCS-4是等同的。
UCS-2
采用2個字節,定長的表示每一個字符,所以總計可以表示2^16個字符。
UCS-4
UCS-4根據最高位為0的最高字節分成2^7=128個group。每個group再根據次高字節分為256個plane。每個plane根據第3個字節分為256行(rows),每行包含256個cells。當然同一行的cells只是最后一個字節不同,其余都相同。
group 0的plane 0被稱作Basic Multilingual Plane, 即BMP。或者說UCS-4中,高兩個字節為0的碼位被稱作BMP。
將UCS-4的BMP去掉前面的兩個零字節就得到了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就得到了UCS-4的BMP。而目前的UCS-4規范中還沒有任何字符被分配在BMP之外。
編碼轉換
請參考
字符編碼之UCS-2與Utf-8
UCS-2和UTF-8的互相轉換
操作系統使用編碼
從Windows2K開始,Win的系統內核開始完全支持并完全應用Unicode編寫,所有ANSI字符在進入底層前,都會被相應的API轉換成Unicode。
Linux 服務器上 UCS-2 編碼方式與 Winodws 不一致,以下是有關兩個平臺 UCS-2 編碼的潛規則:
對于JAVA/.NET/Python等這些“新”的語言來說,內置的字符串所使用的字符集已經完全是Unicode最重要的是,世界上大多數程序用的字符集都是Unicode,因為Unicode有利于程序國際化和標準化。
Python與編碼
我會接著寫另外一篇文章。
參考資料
轉載于:https://www.cnblogs.com/Free-Thinker/p/8309785.html
總結
- 上一篇: krpano·分组图片地图插件
- 下一篇: 内核知识第九讲,32位下的分页管理,36