原作不祥
從基礎(chǔ)的開(kāi)始
? 最小的單元是位(bit),接著是字節(jié)(Byte),一個(gè)字節(jié)=8位,英語(yǔ)表示是1 byte=8 bits 。機(jī)器語(yǔ)言的單位Byte。接著是KB,1 KB=1024 Byte;? 接著是MB,1 MB=1024 KB;? 接著是GB,1 GB=1024 MB ;接著是TB, 1TB=1024 GB。
? 接著是進(jìn)制:二進(jìn)制0和1,8進(jìn)制0-7, 十進(jìn)制不用說(shuō),16進(jìn)制0-9后面是A,B,C,D,E,F 他們關(guān)系如下:
Binary???? Octal? Decimal Hex
0????????? 0????? 0?????? 0
1????????? 1????? 1?????? 1
10???????? 2????? 2?????? 2
11???????? 3????? 3?????? 3
100??????? 4????? 4?????? 4
101??????? 5????? 5?????? 5
110??????? 6????? 6?????? 6
111??????? 7????? 7?????? 7
1000?????? 10???? 8?????? 8
1001?????? 11???? 9?????? 9
1010?????? 12???? 10????? A
1011?????? 13???? 11????? B
1100?????? 14???? 12????? C
1101?????? 15???? 13????? D
1110?????? 16???? 14????? E
1111?????? 17???? 15????? F
接著是上層建筑字符:
? 字符是各種文字和符號(hào)的總稱,包括各國(guó)家文字、標(biāo)點(diǎn)符號(hào)、圖形符號(hào)、數(shù)字等。字符集是多個(gè)字符的集合,字符集種類較多,每個(gè)字符集包含的字符個(gè)數(shù)不同,常見(jiàn)字符集名稱:ASCII字符集、GB2312字符集、BIG5字符集、 GB 18030字符集、Unicode字符集等。計(jì)算機(jī)要準(zhǔn)確的處理各種字符集文字,需要進(jìn)行字符編碼,以便計(jì)算機(jī)能夠識(shí)別和存儲(chǔ)各種文字。
ASCII 字符集
? ASCII(American Standard Code for Information Interchange,美國(guó)信息互換標(biāo)準(zhǔn)代碼)是基于羅馬字母表的一套電腦編碼系統(tǒng),它主要用于顯示現(xiàn)代英語(yǔ)和其他西歐語(yǔ)言。它是現(xiàn)今最通用的單字節(jié)編碼系統(tǒng),并等同于國(guó)際標(biāo)準(zhǔn)ISO 646。
包含內(nèi)容:
控制字符:回車(chē)鍵、退格、換行鍵等。
可顯示字符:英文大小寫(xiě)字符、阿拉伯?dāng)?shù)字和西文符號(hào)
ASCII擴(kuò)展字符集擴(kuò)展:表格符號(hào)、計(jì)算符號(hào)、希臘字母和特殊的拉丁符號(hào)。
第0~32號(hào)及第127號(hào)(共34個(gè))是控制字符或通訊專用字符,如控制符:LF(換行)、CR(回車(chē))、FF(換頁(yè))、DEL(刪除)、BEL(振鈴)等;通訊專用字符:SOH(文頭)、EOT(文尾)、ACK(確認(rèn))等;
第33~126號(hào)(共94個(gè))是字符,其中第48~57號(hào)為0~9十個(gè)阿拉伯?dāng)?shù)字;65~90號(hào)為26個(gè)大寫(xiě)英文字母,97~122號(hào)為26個(gè)小寫(xiě)英文字母,其余為一些標(biāo)點(diǎn)符號(hào)、運(yùn)算符號(hào)等。?
注意:在計(jì)算機(jī)的存儲(chǔ)單元中,一個(gè)ASCII碼值占一個(gè)字節(jié)(8個(gè)二進(jìn)制位),其最高位(b7)用作奇偶校驗(yàn)位。所謂奇偶校驗(yàn),是指在代碼傳送過(guò)程中用來(lái)檢驗(yàn)是否出現(xiàn)錯(cuò)誤的一種方法,一般分奇校驗(yàn)和偶校驗(yàn)兩種。奇校驗(yàn)規(guī)定:正確的代碼一個(gè)字節(jié)中1的個(gè)數(shù)必須是奇數(shù),若非奇數(shù),則在最高位b7添1;偶校驗(yàn)規(guī)定:正確的代碼一個(gè)字節(jié)中1的個(gè)數(shù)必須是偶數(shù),若非偶數(shù),則在最高位b7添1。
DEC?? HEX? CHAR? CODE? C 程序(轉(zhuǎn)義)?
0???? 00 NUL (’\0’)?
1???? 01 SOH ?
2???? 02 STX ?
3???? 03 ETX ?
4???? 04 EOT ?
5???? 05 ENQ ?
6???? 06 ACK ?
7???? 07 BEL (’\a’)?
8???? 08 BS (’\b’)?
9???? 09 HT (’\t’)?
10??? 0A LF (’\n’)?
11??? 0B VT (’\v’)?
12??? 0C FF (’\f’)?
13??? 0D CR (’\r’)?
14??? 0E SO ?
15??? 0F SI ?
16??? 10 DLE ?
17??? 11 DC1 ?
18??? 12 DC2 ?
19??? 13 DC1 ?
20??? 14 DC4 ?
21??? 15 NAK ?
22??? 16 SYN ?
23??? 17 ETB ?
24??? 18 CAN ?
25??? 19 EM ?
26??? 1A SUB ?
27??? 1B ESC ?
28??? 1C FS ?
29??? 1D GS ?
30??? 1E RS ?
31??? 1F US ?
32??? 20 (space,空格) ?
33??? 21??? ! ?
34??? 22??? " ?
35??? 23??? # ?
36??? 24??? $ ?
37??? 25??? % ?
38??? 26??? & ?
39??? 27??? ’ ?
40??? 28??? ( ?
41??? 29??? ) ?
42??? 2A??? * ?
43??? 2B??? + ?
44??? 2C??? , ?
45??? 2D??? - ?
46??? 2E??? . ?
47??? 2F??? / ?
48??? 30??? 0 ?
49??? 31??? 1 ?
50??? 32??? 2 ?
51??? 33??? 3 ?
52??? 34??? 4 ?
53??? 35??? 5 ?
54??? 36??? 6 ?
55??? 37??? 7 ?
56??? 38??? 8 ?
57??? 39??? 9 ?
58??? 3A??? : ?
59??? 3B??? ; ?
60??? 3C??? < ?
61??? 3D??? = ?
62??? 3E??? > ?
63??? 3F??? ? ?
64??? 40??? @ ?
65??? 41??? A ?
66??? 42??? B ?
67??? 43??? C ?
68??? 44??? D ?
69??? 45??? E ?
70??? 46??? F ?
71??? 47??? G ?
72??? 48??? H ?
73??? 49??? I ?
74??? 4A??? J ?
75??? 4B??? K ?
76??? 4C??? L ?
77??? 4D??? M ?
78??? 4E??? N ?
79??? 4F??? O ?
80??? 50??? P ?
81??? 51??? Q ?
82??? 52??? R ?
83??? 53??? S ?
84??? 54??? T ?
85??? 55??? U ?
86??? 56??? V ?
87??? 57??? W ?
88??? 58??? X ?
89??? 59??? Y ?
90??? 5A??? Z ?
91??? 5B??? [ ?
92??? 5C??? \ (’\\’)?
93??? 5D??? ] ?
94??? 5E??? ^ ?
95??? 5F??? _ ?
96??? 60??? ` ?
97??? 61??? a ?
98??? 62??? b ?
99??? 63??? c ?
100?? 64??? d ?
101?? 65??? e ?
102?? 66??? f ?
103?? 67??? g ?
104?? 68??? h ?
105?? 69??? i ?
106?? 6A??? j ?
107?? 6B??? k ?
108?? 6C??? l ?
109?? 6D??? m ?
110?? 6E??? n ?
111?? 6F??? o ?
112?? 70??? p ?
113?? 71??? q ?
114?? 72??? r ?
115?? 73??? s ?
116?? 74??? t ?
117?? 75??? u ?
118?? 76??? v ?
119?? 77??? w ?
120?? 78??? x ?
121?? 79??? y ?
122?? 7A??? z ?
123?? 7B??? { ?
124?? 7C??? | ?
125?? 7D??? } ?
126?? 7E??? ~ ?
127?? 7F???? DEL
GB2312 字符集
? GB2312又稱為GB2312-80字符集,全稱為《信息交換用漢字編碼字符集·基本集》,由原中國(guó)國(guó)家標(biāo)準(zhǔn)總局發(fā)布,1981年5月1日實(shí)施,是中國(guó)國(guó)家標(biāo)準(zhǔn)的簡(jiǎn)體中文字符集。它所收錄的漢字已經(jīng)覆蓋99.75%的使用頻率,基本滿足了漢字的計(jì)算機(jī)處理需要。在中國(guó)大陸和新加坡獲廣泛使用。
?
? GB2312收錄簡(jiǎn)化漢字及一般符號(hào)、序號(hào)、數(shù)字、拉丁字母、日文假名、希臘字母、俄文字母、漢語(yǔ)拼音符號(hào)、漢語(yǔ)注音字母,共 7445 個(gè)圖形字符。其中包括6763個(gè)漢字,其中一級(jí)漢字3755個(gè),二級(jí)漢字3008個(gè);包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語(yǔ)西里爾字母在內(nèi)的682個(gè)全角字符。
? GB2312中對(duì)所收漢字進(jìn)行了“分區(qū)”處理,每區(qū)含有94個(gè)漢字/符號(hào)。這種表示方式也稱為區(qū)位碼。
它是用雙字節(jié)表示的,兩個(gè)字節(jié)中前面的字節(jié)為第一字節(jié),后面的字節(jié)為第二字節(jié)。習(xí)慣上稱第一字節(jié)為“高字節(jié)” ,而稱第二字節(jié)為“低字節(jié)”。“高位字節(jié)”使用了0xA1-0xF7(把01-87區(qū)的區(qū)號(hào)加上0xA0),“低位字節(jié)”使用了0xA1-0xFE(把01-94加上0xA0)。
? 以GB2312字符集的第一個(gè)漢字“啊”字為例,它的區(qū)號(hào)16,位號(hào)01,則區(qū)位碼是1601,在大多數(shù)計(jì)算機(jī)程序中,高字節(jié)和低字節(jié)分別加0xA0得到程序的漢字處理編碼0xB0A1。計(jì)算公式是:0xB0=0xA0+16, 0xA1=0xA0+1。
GBK字符集
? GBK字符集是GB2312的擴(kuò)展(K),GBK1.0收錄了21886個(gè)符號(hào),它分為漢字區(qū)和圖形符號(hào)區(qū),漢字區(qū)包括21003個(gè)字符。GBK字符集主要擴(kuò)展了繁體中文字的支持。
BIG5 字符集
? BIG5又稱大五碼或五大碼,1984年由臺(tái)灣財(cái)團(tuán)法人信息工業(yè)策進(jìn)會(huì)和五間軟件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大眾 (FIC)創(chuàng)立,故稱大五碼。Big5碼的產(chǎn)生,是因?yàn)楫?dāng)時(shí)臺(tái)灣不同廠商各自推出不同的編碼,如倚天碼、IBM PS55、王安碼等,彼此不能兼容;另一方面,臺(tái)灣政府當(dāng)時(shí)尚未推出官方的漢字編碼,而中國(guó)大陸的GB2312編碼亦未有收錄繁體中文字。
? Big5字符集共收錄13,053個(gè)中文字,該字符集在中國(guó)臺(tái)灣使用。耐人尋味的是該字符集重復(fù)地收錄了兩個(gè)相同的字:“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。
? Big5碼使用了雙字節(jié)儲(chǔ)存方法,以兩個(gè)字節(jié)來(lái)編碼一個(gè)字。第一個(gè)字節(jié)稱為“高位字節(jié)”,第二個(gè)字節(jié)稱為“低位字節(jié)”。高位字節(jié)的編碼范圍0xA1-0xF9,低位字節(jié)的編碼范圍0x40-0x7E及0xA1-0xFE。
? 盡管Big5碼內(nèi)包含一萬(wàn)多個(gè)字符,但是沒(méi)有考慮社會(huì)上流通的人名、地名用字、方言用字、化學(xué)及生物科等用字,沒(méi)有包含日文平假名及片假字母。
例如臺(tái)灣視“著”為“著”的異體字,故沒(méi)有收錄“著”字。康熙字典中的一些部首用字(如“亠”、“疒”、“辵”、“癶”等)、常見(jiàn)的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也沒(méi)有收錄到Big5之中。
GB18030 字符集
GB18030的全稱是GB18030-2000《信息交換用漢字編碼字符集基本集的擴(kuò)充》,是我國(guó)政府于2000年3月17日發(fā)布的新的漢字編碼國(guó)家標(biāo)準(zhǔn),2001年8月31日后在中國(guó)市場(chǎng)上發(fā)布的軟件必須符合本標(biāo)準(zhǔn)。GB 18030字符集標(biāo)準(zhǔn)的出臺(tái)經(jīng)過(guò)廣泛參與和論證,來(lái)自國(guó)內(nèi)外知名信息技術(shù)行業(yè)的公司,信息產(chǎn)業(yè)部和原國(guó)家質(zhì)量技術(shù)監(jiān)督局聯(lián)合實(shí)施。
GB 18030字符集標(biāo)準(zhǔn)解決漢字、日文假名、朝鮮語(yǔ)和中國(guó)少數(shù)民族文字組成的大字符集計(jì)算機(jī)編碼問(wèn)題。該標(biāo)準(zhǔn)的字符總編碼空間超過(guò)150萬(wàn)個(gè)編碼位,收錄了27484個(gè)漢字,覆蓋中文、日文、朝鮮語(yǔ)和中國(guó)少數(shù)民族文字。滿足中國(guó)大陸、香港、臺(tái)灣、日本和韓國(guó)等東亞地區(qū)信息交換多文種、大字量、多用途、統(tǒng)一編碼格式的要求。并且與Unicode 3.0版本兼容,填補(bǔ)Unicode擴(kuò)展字符字匯“統(tǒng)一漢字?jǐn)U展A”的內(nèi)容。并且與以前的國(guó)家字符編碼標(biāo)準(zhǔn)(GB2312,GB13000.1)兼容。
編碼方法:
GB 18030標(biāo)準(zhǔn)采用單字節(jié)、雙字節(jié)和四字節(jié)三種方式對(duì)字符編碼。單字節(jié)部分使用0×00至0×7F碼(對(duì)應(yīng)于ASCII碼的相應(yīng)碼)。雙字節(jié)部分,首字節(jié)碼從0×81至0×FE,尾字節(jié)碼位分別是0×40至0×7E和0×80至0×FE。四字節(jié)部分采用GB/T 11383未采用的0×30到0×39作為對(duì)雙字節(jié)編碼擴(kuò)充的后綴,這樣擴(kuò)充的四字節(jié)編碼,其范圍為0×81308130到0×FE39FE39。其中第一、三個(gè)字節(jié)編碼碼位均為0×81至0×FE,第二、四個(gè)字節(jié)編碼碼位均為0×30至0×39。
按照程序員的稱呼,GB2312、GBK到GB18030都屬于雙字節(jié)字符集 (DBCS)。
接著是國(guó)際通用的unicode字符集
Unicode字符集(簡(jiǎn)稱為UCS)
1.名稱的由來(lái)
Unicode字符集編碼是(Universal Multiple-Octet Coded Character Set) 通用多八位編碼字符集的簡(jiǎn)稱,支持世界上超過(guò)650種語(yǔ)言的國(guó)際字符集。Unicode允許在同一服務(wù)器上混合使用不同語(yǔ)言組的不同語(yǔ)言。它是由一個(gè)名為 Unicode 學(xué)術(shù)學(xué)會(huì)(Unicode Consortium)的機(jī)構(gòu)制訂的字符編碼系統(tǒng),支持現(xiàn)今世界各種不同語(yǔ)言的書(shū)面文本的交換、處理及顯示。該編碼于1990年開(kāi)始研發(fā),1994年正式公布,最新版本是2005年3月31日的Unicode 4.1.0。Unicode是一種在計(jì)算機(jī)上使用的字符編碼。它為每種語(yǔ)言中的每個(gè)字符設(shè)定了統(tǒng)一并且唯一的二進(jìn)制編碼,以滿足跨語(yǔ)言、跨平臺(tái)進(jìn)行文本轉(zhuǎn)換、處理的要求。
2.編碼方法
Unicode 標(biāo)準(zhǔn)始終使用十六進(jìn)制數(shù)字,而且在書(shū)寫(xiě)時(shí)在前面加上前綴“U+”,例如字母“A”的編碼為 004116 。所以“A”的編碼書(shū)寫(xiě)為“U+0041”。
3.UTF-8 編碼
UTF-8是Unicode的其中一個(gè)使用方式。 UTF是 Unicode Translation Format,即把Unicode轉(zhuǎn)做某種格式的意思。
UTF-8便于不同的計(jì)算機(jī)之間使用網(wǎng)絡(luò)傳輸不同語(yǔ)言和編碼的文字,使得雙字節(jié)的Unicode能夠在現(xiàn)存的處理單字節(jié)的系統(tǒng)上正確傳輸。
UTF-8使用可變長(zhǎng)度字節(jié)來(lái)儲(chǔ)存 Unicode字符,例如ASCII字母繼續(xù)使用1字節(jié)儲(chǔ)存,重音文字、希臘字母或西里爾字母等使用2字節(jié)來(lái)儲(chǔ)存,而常用的漢字就要使用3字節(jié)。輔助平面字符則使用4字節(jié)。
4.UTF-16 和 UTF-32 編碼
UTF-32、UTF-16 和 UTF-8 是 Unicode 標(biāo)準(zhǔn)的編碼字符集的字符編碼方案,UTF-16 使用一個(gè)或兩個(gè)未分配的 16 位代碼單元的序列對(duì) Unicode 代碼點(diǎn)進(jìn)行編碼;UTF-32 即將每一個(gè) Unicode 代碼點(diǎn)表示為相同值的 32 位整數(shù)
通過(guò)一個(gè)問(wèn)題了解unicode編碼
?
問(wèn)題:使用Windows記事本的“另存為”,可以在ANSI、GBK、Unicode、Unicode big endian和UTF-8這幾種編碼方式間相互轉(zhuǎn)換。同樣是txt文件,Windows怎樣識(shí)別編碼方式的呢?
我很早前就發(fā)現(xiàn)Unicode、Unicode big endian和UTF-8編碼的txt文件的開(kāi)頭會(huì)多出幾個(gè)字節(jié),分別是FF、FE(Unicode),FE、FF(Unicode big endian),EF、BB、BF(UTF-8)。但這些標(biāo)記是基于什么標(biāo)準(zhǔn)呢?
答案:
ANSI字符集定義:ASCII字符集,以及由此派生并兼容的字符集,如:GB2312,正式的名稱為MBCS(Multi-Byte Chactacter System,多字節(jié)字符系統(tǒng)),通常也稱為ANSI字符集。
UNICODE 與 UTF8、UTF16
? 由于每種語(yǔ)言都制定了自己的字符集,導(dǎo)致最后存在的各種字符集實(shí)在太多,在國(guó)際交流中要經(jīng)常轉(zhuǎn)換字符集非常不便。因此,產(chǎn)生了Unicode字符集,它固定使用16 bits(兩個(gè)字節(jié))來(lái)表示一個(gè)字符,共可以表示65536個(gè)字符
? 標(biāo)準(zhǔn)的 Unicode 稱為UTF-16(UTF:UCS Transformation Format )。后來(lái)為了雙字節(jié)的Unicode能夠在現(xiàn)存的處理單字節(jié)的系統(tǒng)上正確傳輸,出現(xiàn)了UTF-8,使用類似MBCS的方式對(duì)Unicode進(jìn)行編碼。(Unicode字符集有多種編碼形式)
例如"連通"兩個(gè)字的Unicode標(biāo)準(zhǔn)編碼UTF-16 (big endian)為:DE 8F 1A 90?
而其UTF-8編碼為:E8 BF 9E E9 80 9A
當(dāng)一個(gè)軟件打開(kāi)一個(gè)文本時(shí),它要做的第一件事是決定這個(gè)文本究竟是使用哪種字符集的哪種編碼保存的。軟件一般采用三種方式來(lái)決定文本的字符集和編碼:
檢測(cè)文件頭標(biāo)識(shí),提示用戶選擇,根據(jù)一定的規(guī)則猜測(cè)
最標(biāo)準(zhǔn)的途徑是檢測(cè)文本最開(kāi)頭的幾個(gè)字節(jié),開(kāi)頭字節(jié) Charset/encoding,如下表:
EF BB BF????? UTF-8
FE FF?????????? UTF-16/UCS-2, little endian
FF FE?????????? UTF-16/UCS-2, big endian
FF FE 00 00? UTF-32/UCS-4, little endian.
00 00 FE FF? UTF-32/UCS-4, big-endian.?
1、big endian和little endian
big endian和little endian是CPU處理多字節(jié)數(shù)的不同方式。例如“漢”字的Unicode編碼是6C49。那么寫(xiě)到文件里時(shí),究竟是將6C寫(xiě)在前面,還是將49寫(xiě)在前面?如果將6C寫(xiě)在前面,就是big endian。還是將49寫(xiě)在前面,就是little endian。
“endian”這個(gè)詞出自《格列佛游記》。小人國(guó)的內(nèi)戰(zhàn)就源于吃雞蛋時(shí)是究竟從大頭(Big-Endian)敲開(kāi)還是從小頭(Little-Endian)敲開(kāi),由此曾發(fā)生過(guò)六次叛亂,其中一個(gè)皇帝送了命,另一個(gè)丟了王位。
我們一般將endian翻譯成“字節(jié)序”,將big endian和little endian稱作“大尾”和“小尾”。
2、字符編碼、內(nèi)碼,順帶介紹漢字編碼
? 字符必須編碼后才能被計(jì)算機(jī)處理。計(jì)算機(jī)使用的缺省編碼方式就是計(jì)算機(jī)的內(nèi)碼。早期的計(jì)算機(jī)使用7位的ASCII編碼,為了處理漢字,程序員設(shè)計(jì)了用于簡(jiǎn)體中文的GB2312和用于繁體中文的big5。
GB2312(1980年)一共收錄了7445個(gè)字符,包括6763個(gè)漢字和682個(gè)其它符號(hào)。漢字區(qū)的內(nèi)碼范圍高字節(jié)從B0-F7,低字節(jié)從A1-FE,占用的碼位是72*94=6768。其中有5個(gè)空位是D7FA-D7FE。
GB2312支持的漢字太少。1995年的漢字?jǐn)U展規(guī)范GBK1.0收錄了21886個(gè)符號(hào),它分為漢字區(qū)和圖形符號(hào)區(qū)。漢字區(qū)包括21003個(gè)字符。2000年的GB18030是取代GBK1.0的正式國(guó)家標(biāo)準(zhǔn)。該標(biāo)準(zhǔn)收錄了27484個(gè)漢字,同時(shí)還收錄了藏文、蒙文、維吾爾文等主要的少數(shù)民族文字。現(xiàn)在的PC平臺(tái)必須支持GB18030,對(duì)嵌入式產(chǎn)品暫不作要求。所以手機(jī)、MP3一般只支持GB2312。
從ASCII、GB2312、GBK到GB18030,這些編碼方法是向下兼容的,即同一個(gè)字符在這些方案中總是有相同的編碼,后面的標(biāo)準(zhǔn)支持更多的字符。在這些編碼中,英文和中文可以統(tǒng)一地處理。區(qū)分中文編碼的方法是高字節(jié)的最高位不為0。按照程序員的稱呼,GB2312、GBK到GB18030都屬于雙字節(jié)字符集 (DBCS)。
有的中文Windows的缺省內(nèi)碼還是GBK,可以通過(guò)GB18030升級(jí)包升級(jí)到GB18030。不過(guò)GB18030相對(duì)GBK增加的字符,普通人是很難用到的,通常我們還是用GBK指代中文Windows內(nèi)碼。
這里還有一些細(xì)節(jié):
GB2312的原文還是區(qū)位碼,從區(qū)位碼到內(nèi)碼,需要在高字節(jié)和低字節(jié)上分別加上A0。
在DBCS中,GB內(nèi)碼的存儲(chǔ)格式始終是big endian,即高位在前。
GB2312的兩個(gè)字節(jié)的最高位都是1。但符合這個(gè)條件的碼位只有128*128=16384個(gè)。所以GBK和GB18030的低字節(jié)最高位都可能不是1。不過(guò)這不影響DBCS字符流的解析:在讀取DBCS字符流時(shí),只要遇到高位為1的字節(jié),就可以將下兩個(gè)字節(jié)作為一個(gè)雙字節(jié)編碼,而不用管低字節(jié)的高位是什么。
3、Unicode、UCS和UTF(UCS Transformation Format)
前面提到從ASCII、GB2312、GBK到GB18030的編碼方法是向下兼容的。而Unicode只與ASCII兼容(更準(zhǔn)確地說(shuō),是與ISO-8859-1兼容),與GB碼不兼容。例如“漢”字的Unicode編碼是6C49,而GB碼是BABA。
? UCS規(guī)定了怎么用多個(gè)字節(jié)表示各種文字。而怎樣傳輸這些編碼,是由UTF(UCS Transformation Format)規(guī)范規(guī)定的!常見(jiàn)的UTF規(guī)范包括UTF-8、UTF-7、UTF-16。
4、UTF的字節(jié)序和BOM
UTF-8以字節(jié)為編碼單元,沒(méi)有字節(jié)序的問(wèn)題。UTF-16以兩個(gè)字節(jié)為編碼單元,在解釋一個(gè)UTF-16文本前,首先要弄清楚每個(gè)編碼單元的字節(jié)序。例如收到一個(gè)“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節(jié)流“594E”,那么這是“奎”還是“乙”?
Unicode規(guī)范中推薦的標(biāo)記字節(jié)順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一個(gè)有點(diǎn)小聰明的想法:
在UCS編碼中有一個(gè)叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應(yīng)該出現(xiàn)在實(shí)際傳輸中。UCS規(guī)范建議我們?cè)趥鬏斪止?jié)流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。
這樣如果接收者收到FEFF,就表明這個(gè)字節(jié)流是Big-Endian的;如果收到FFFE,就表明這個(gè)字節(jié)流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。
UTF-8不需要BOM來(lái)表明字節(jié)順序,但可以用BOM來(lái)表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗(yàn)證一下)。所以如果接收者收到以EF BB BF開(kāi)頭的字節(jié)流,就知道這是UTF-8編碼了。
Windows就是使用BOM來(lái)標(biāo)記文本文件的編碼方式的。
? 寫(xiě)到這里對(duì)編碼有了大致的了解了,就可以理解網(wǎng)上一些文章的話了,比如有一篇很流行的文章《URL編碼與SQL注射》里面有一段是這么說(shuō)的:
其實(shí)url編碼就是一個(gè)字符ascii碼的十六進(jìn)制。不過(guò)稍微有些變動(dòng),需要在前面加上“%”。比如“\”,它的ascii碼是92,92的十六進(jìn)制是5c,所以“\”的url編碼就是%5c。那么漢字的url編碼呢?很簡(jiǎn)單,看例子:“胡”的ascii碼是-17670,十六進(jìn)制是BAFA,url編碼是“%BA%FA”。呵呵,知道怎么轉(zhuǎn)換的了吧。
?? 這得從ASCII說(shuō)起,擴(kuò)展的ASCII字符集采用8bit255個(gè)字符顯然不夠用,于是各個(gè)國(guó)家紛紛制定了自己的文字編碼規(guī)范,其中中文的文字編碼規(guī)范叫做“GB2312-80”(就是GB2312),它是和ASCII兼容的一種編碼規(guī)范,其實(shí)就是用擴(kuò)展ASCII沒(méi)有真正標(biāo)準(zhǔn)化這一點(diǎn),把一個(gè)中文字符用兩個(gè)擴(kuò)展ASCII字符來(lái)表示。文中說(shuō)的的中文ASCII碼實(shí)際上就是簡(jiǎn)體中文的編碼2312GB!它把ASCII又?jǐn)U充了一個(gè)字節(jié),由于高位的第一位是0,所以會(huì)出現(xiàn)負(fù)數(shù)的形式,url編碼就是將漢字的這個(gè)GB2312編碼轉(zhuǎn)化成UTF-8的編碼并且每8位即一個(gè)字節(jié)前面加上%符號(hào)表示。
那為何UTF-8是進(jìn)行網(wǎng)絡(luò)的規(guī)范傳輸編碼呢?
在Unicode里,所有的字符被一視同仁。漢字不再使用“兩個(gè)擴(kuò)展ASCII”,而是使用“1個(gè)Unicode”,注意,現(xiàn)在的漢字是“一個(gè)字符”了,于是,拆字、統(tǒng)計(jì)字?jǐn)?shù)這些問(wèn)題也就自然而然的解決了。但是,這個(gè)世界不是理想的,不可能在一夜之間所有的系統(tǒng)都使用Unicode來(lái)處理字符,所以Unicode在誕生之日,就必須考慮一個(gè)嚴(yán)峻的問(wèn)題:和ASCII字符集之間的不兼容問(wèn)題。
我們知道,ASCII字符是單個(gè)字節(jié)的,比如“A”的ASCII是65。而Unicode是雙字節(jié)的,比如“A”的Unicode是0065,這就造成了一個(gè)非常大的問(wèn)題:以前處理ASCII的那套機(jī)制不能被用來(lái)處理Unicode了
另一個(gè)更加嚴(yán)重的問(wèn)題是,C語(yǔ)言使用'\0'作為字符串結(jié)尾,而Unicode里恰恰有很多字符都有一個(gè)字節(jié)為0,這樣一來(lái),C語(yǔ)言的字符串函數(shù)將無(wú)法正常處理Unicode,除非把世界上所有用C寫(xiě)的程序以及他們所用的函數(shù)庫(kù)全部換掉
于是,比Unicode更偉大的東東誕生了,之所以說(shuō)它更偉大是因?yàn)樗孶nicode不再存在于紙上,而是真實(shí)的存在于我們大家的電腦中。那就是:UTF
UTF= UCS Transformation Format UCS轉(zhuǎn)換格式,它是將Unicode編碼規(guī)則和計(jì)算機(jī)的實(shí)際編碼對(duì)應(yīng)起來(lái)的一個(gè)規(guī)則。現(xiàn)在流行的UTF有2種:UTF-8和UTF-16
其中UTF-16和上面提到的Unicode本身的編碼規(guī)范是一致的,這里不多說(shuō)了。而UTF-8不同,它定義了一種“區(qū)間規(guī)則”,這種規(guī)則可以和ASCII編碼保持最大程度的兼容,這樣做的好處是壓縮了字符在西歐一些國(guó)家的內(nèi)存消耗,減少了不必要的資源浪費(fèi),這在實(shí)際應(yīng)用中是非常有必要的。
UTF-8有點(diǎn)類似于Haffman編碼,它將Unicode編碼為:
00000000-0000007F的字符,用單個(gè)字節(jié)來(lái)表示;
00000080-000007FF的字符用兩個(gè)字節(jié)表示? (中文的編碼范圍)
00000800-0000FFFF的字符用3字節(jié)表示
因?yàn)槟壳盀橹筓nicode-16規(guī)范沒(méi)有指定FFFF以上的字符,所以UTF-8最多是使用3個(gè)字節(jié)來(lái)表示一個(gè)字符。但理論上來(lái)說(shuō),UTF-8最多需要用6字節(jié)表示一個(gè)字符。
在UTF-8里,英文字符仍然跟ASCII編碼一樣,因此原先的函數(shù)庫(kù)可以繼續(xù)使用。而中文的編碼范圍是在0080-07FF之間,因此是2個(gè)字節(jié)表示(但這兩個(gè)字節(jié)和GB編碼的兩個(gè)字節(jié)是不同的)。
看看編碼之多:ANSI,AscII,GB2312,GBK,BIG5,GB18030,Unicode,UCS(就是unicode)Utf-8,utf-16,utf-32 整整10種編碼~,算是夠復(fù)雜了
可是這還僅僅是個(gè)開(kāi)始,應(yīng)用方面變化無(wú)窮,不過(guò)現(xiàn)在看到這些東西起碼再不會(huì)頭大了!呼呼~
哦,漏了一個(gè)加密的base64編碼。
什么是Base64?
按照RFC2045的定義,Base64被定義為:Base64內(nèi)容傳送編碼被設(shè)計(jì)用來(lái)把任意序列的8位字節(jié)描述為一種不易被人直接識(shí)別的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
為什么要使用Base64?
在設(shè)計(jì)這個(gè)編碼的時(shí)候,我想設(shè)計(jì)人員最主要考慮了3個(gè)問(wèn)題:
1.是否加密?
2.加密算法復(fù)雜程度和效率
3.如何處理傳輸?
??? 加密是肯定的,但是加密的目的不是讓用戶發(fā)送非常安全的Email。這種加密方式主要就是“防君子不防小人”。即達(dá)到一眼望去完全看不出內(nèi)容即可。
基于這個(gè)目的加密算法的復(fù)雜程度和效率也就不能太大和太低。和上一個(gè)理由類似,MIME協(xié)議等用于發(fā)送Email的協(xié)議解決的是如何收發(fā)Email,而并不是如何安全的收發(fā)Email。因此算法的復(fù)雜程度要小,效率要高,否則因?yàn)榘l(fā)送Email而大量占用資源,路就有點(diǎn)走歪了。
??? 但是,如果是基于以上兩點(diǎn),那么我們使用最簡(jiǎn)單的愷撒法即可,為什么Base64看起來(lái)要比愷撒法復(fù)雜呢?這是因?yàn)樵贓mail的傳送過(guò)程中,由于歷史原因,Email只被允許傳送ASCII字符,即一個(gè)8位字節(jié)的低7位。因此,如果您發(fā)送了一封帶有非ASCII字符(即字節(jié)的最高位是1)的Email通過(guò)有“歷史問(wèn)題”的網(wǎng)關(guān)時(shí)就可能會(huì)出現(xiàn)問(wèn)題。網(wǎng)關(guān)可能會(huì)把最高位置為0!很明顯,問(wèn)題就這樣產(chǎn)生了!因此,為了能夠正常的傳送Email,這個(gè)問(wèn)題就必須考慮!所以,單單靠改變字母的位置的愷撒之類的方案也就不行了。關(guān)于這一點(diǎn)可以參考RFC2046。
基于以上的一些主要原因產(chǎn)生了Base64編碼。
鑒于算法比較讓人頭大,想看的人自然會(huì)有看到的辦法拉,俺是頭大得很,就不放上來(lái)了。