但是我這個的特點是追究原理,我在乎的事情都想弄明白,于是各個qq群依次發(fā)信息,沒人理會。唉,郁悶。只好自己google it and teach myself 。下面是詳細(xì)介紹。
還有對各方求助沒有人理會,我有些個人想法。現(xiàn)在的人已經(jīng)很少有人去深究理論了,人們的觀念是得過且過,人們通常只是知道什么,不知道為什么。對編程來說,個人認(rèn)為這是很悲哀的事情,也是非常危險的事情。我想可能這也是中國的IT落后于美國的原因,我希望中國的編程人員能夠好好想想了。
下面的東西是從網(wǎng)上查到的
Unicode 的編碼和實現(xiàn)
大概來說,Unicode 編碼系統(tǒng)可分為編碼方式和實現(xiàn)方式兩個層次。
編碼方式
Unicode 的編碼方式與 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相對應(yīng),目前實際應(yīng)用的 Unicode 版本對應(yīng)于 UCS-2,使用16位的編碼空間。也就是每個字符占用2個字節(jié)。這樣理論上一共最多可以表示 216 即 65536 個字符?;緷M足各種語言的使用。實際上目前版本的 Unicode 尚未填充滿這16位編碼,保留了大量空間作為特殊使用或?qū)頂U展。
上述16位 Unicode 字符構(gòu)成基本多文種平面(Basic Multilingual Plane,簡稱 BMP)。最新(但未實際廣泛使用)的 Unicode 版本定義了16個輔助平面,兩者合起來至少需要占據(jù)21位的編碼空間,比3字節(jié)略少。但事實上輔助平面字符仍然占用4字節(jié)編碼空間,與 UCS-4 保持一致。未來版本會擴充到 ISO 10646-1 實現(xiàn)級別3,即涵蓋 UCS-4 的所有字符。UCS-4 是一個更大的尚未填充完全的31位字符集,加上恒為0的首位,共需占據(jù)32位,即4字節(jié)。理論上最多能表示 231 個字符,完全可以涵蓋一切語言所用的符號。
BMP 字符的 Unicode 編碼表示為 U+hhhh,其中每個 h 代表一個十六進制數(shù)位。與 UCS-2 編碼完全相同。對應(yīng)的4字節(jié) UCS-4 編碼后兩個字節(jié)一致,前兩個字節(jié)的所有位均為0。
關(guān)于 Unicode 和 ISO 10646 及 UCS 的詳細(xì)關(guān)系 ,請參看通用字符集。
實現(xiàn)方式
Unicode 的實現(xiàn)方式不同于編碼方式。一個字符的 Unicode 編碼是確定的。但是在實際傳輸過程中,由于不同系統(tǒng)平臺的設(shè)計不一定一致,以及出于節(jié)省空間的目的,對 Unicode 編碼的實現(xiàn)方式有所不同。Unicode 的實現(xiàn)方式稱為Unicode轉(zhuǎn)換格式(Unicode Translation Format,簡稱為 UTF)。
例如,如果一個僅包含基本7位ASCII字符的 Unicode 文件,如果每個字符都使用2字節(jié)的原 Unicode 編碼傳輸,其第一字節(jié)的8位始終為0。這就造成了比較大的浪費。對于這種情況,可以使用 UTF-8 編碼,這是一種變長編碼,它將基本7位ASCII字符仍用7位編碼表示,占用一個字節(jié)(首位補0)。而遇到與其他 Unicode 字符混合的情況,將按一定算法轉(zhuǎn)換,每個字符使用1-3個字節(jié)編碼,并利用首位為0或1進行識別。這樣對以7位ASCII字符為主的西文文檔就大大節(jié)省了編碼長度(具體方案參見UTF-8)。類似的,對未來會出現(xiàn)的需要4個字節(jié)的輔助平面字符和其他 UCS-4 擴充字符,2字節(jié)編碼的 UTF-16 也需要通過一定的算法進行轉(zhuǎn)換。
再如,如果直接使用與 Unicode 編碼一致(僅限于 BMP 字符)的 UTF-16 編碼,由于每個字符占用了兩個字節(jié),在Macintosh (Mac)機和PC機上,對字節(jié)順序的理解是不一致的。這時同一字節(jié)流可能會被解釋為不同內(nèi)容,如某字符為十六進制編碼4E59,按兩個字節(jié)拆分為4E和59,在Mac上讀取時是從低字節(jié)開始,那么在Mac OS會認(rèn)為此4E59編碼為594E,找到的字符為“奎”,而在Windows上從高字節(jié)開始讀取,則編碼為 U+4E59 的字符為“乙”。就是說在Windows下以UTF-16編碼保存一個字符“乙”,在Mac OS里打開會顯示成“奎”。此類情況說明UTF-16的編碼順序若不加以人為定義就可能發(fā)生混淆,于是在 UTF-16 編碼實現(xiàn)方式中使用了大尾序(Big-Endian, 簡寫為UTF-16 BE)、小尾序(Little-Endian, 簡寫為UTF-16 LE)的概念,以及可附加的BOM(Byte Order Mark)解決方案,目前在PC機上的Windows系統(tǒng)和Linux系統(tǒng)對于UTF-16編碼默認(rèn)使用UTF-16 LE。(具體方案參見UTF-16)
此外 Unicode 的實現(xiàn)方式還包括 UTF-7、Punycode、CESU-8、SCSU、UTF-32等,這些實現(xiàn)方式有些僅在一定的國家和地區(qū)使用,有些則屬于未來的規(guī)劃方式。目前通用的實現(xiàn)方式是 UTF-16小尾序(BOM)、UTF-16大尾序(BOM)和 UTF-8。在微軟公司Windows XP操作系統(tǒng)附帶的記事本(Notepad)中,“另存為”對話框可以選擇的四種編碼方式除去非 Unicode 編碼的ANSI(對于英文系統(tǒng)即ASCII編碼,中文系統(tǒng)則為GB2312或Big5編碼) 外,其余三種為“Unicode”(對應(yīng)UTF-16 LE)、“Unicode big endian”(對應(yīng)UTF-16 BE)和“UTF-8”。
目前輔助平面的工作主要集中在第二和第三平面的中日韓統(tǒng)一表意文字中,因此包括GBK、GB18030、Big5等簡體中文、繁體中文、日文、韓文以及越南喃字的各種編碼與 Unicode 的協(xié)調(diào)性被重點關(guān)注。考慮到 Unicode 最終要涵蓋所有的字符,從某種意義而言,這些編碼方式也可視作 Unicode 的出現(xiàn)于其之前的既成事實的實現(xiàn)方式,如同ASCII及其擴展Latin-1一樣,后兩者的字符在16位 Unicode 編碼空間中的編碼第一字節(jié)各位全為0,第二字節(jié)編碼與原編碼完全一致。但上述東亞語言編碼與 Unicode 編碼的對應(yīng)關(guān)系要復(fù)雜得多。
utf-8
UTF-8(8 位元 Universal Character Set/Unicode Transformation Format)是一種針對 Unicode 的可變長度字符編碼。它可以用來表示 Unicode 標(biāo)準(zhǔn)中的任何字符,且其編碼中的第一個字節(jié)仍與 ASCII 相容,這使得原來處理 ASCII 字符的軟件無須或只須做少部份修改,即可繼續(xù)使用。因此,它逐漸成為電子郵件、網(wǎng)頁及其他儲存或傳送文字的應(yīng)用中,優(yōu)先采用的編碼。
UTF-8 使用一至四個字節(jié)為每個字符編碼:
- 128 個 US-ASCII 字符只需一個字節(jié)編碼(Unicode 范圍由 U+0000 至 U+007F)。
- 帶有附加符號的拉丁文、希臘文、西里爾字母、亞美尼亞語、希伯來文、阿拉伯文、敘利亞文及它拿字母則需要二個字節(jié)編碼(Unicode 范圍由 U+0080 至 U+07FF)。
- 其他基本多文種平面(BMP)中的字符(這包含了大部分常用字)使用三個字節(jié)編碼。
- 其他極少使用的 Unicode 輔助平面的字符使用四字節(jié)編碼。
對上述提及的第四種字符而言,UTF-8 使用四個字節(jié)來編碼似乎太耗費資源了。但 UTF-8 對所有常用的字符都可以用三個字節(jié)表示,而且它的另一種選擇,UTF-16編碼,對前述的第四種字符同樣需要四個字節(jié)來編碼,所以要決定 UTF-8 或 UTF-16 哪種編碼比較有效率,還要視所使用的字符的分布范圍而定。不過,如果使用一些傳統(tǒng)的壓縮系統(tǒng),比如 DEFLATE,則這些不同編碼系統(tǒng)間的的差異就變得微不足道了。若顧及傳統(tǒng)壓縮算法在壓縮較短文字上的效果不大,可以考慮使用 Standard Compression Scheme for Unicode(SCSU)。
Unicode字符的位元被分割為數(shù)個部分,并分配到UTF-8的字節(jié)串中較低的位元的位置。在U+0080的以下字符都使用內(nèi)含其字符的單字節(jié)編碼。這些編碼正好對應(yīng)7位元的ASCII字符。在其他情況,有可能需要多達(dá)4個字符組來表示一個字符。這些多字節(jié)的最高有效位元會設(shè)定成1,以防止與7位元的ASCII字符混淆,并保持標(biāo)準(zhǔn)的字節(jié)主導(dǎo)字串(standard byte-oriented string)運作順利。
代碼范圍 十六進制 |
標(biāo)量值(scalar value) 二進制 |
UTF-8 二進制/十六進制 |
注釋 |
000000 - 00007F 128個代碼 |
00000000 00000000 0zzzzzzz |
0zzzzzzz(00-7F) |
ASCII字符范圍,字節(jié)由零開始 |
七個z |
七個z |
000080 - 0007FF 1920個代碼 |
00000000 00000yyy yyzzzzzz |
110yyyyy(C2-DF) 10zzzzzz(80-BF) |
第一個字節(jié)由110開始,接著的字節(jié)由10開始 |
三個y;二個y;六個z |
五個y;六個z |
000800 - 00D7FF 00E000 - 00FFFF 61440個代碼 [Note 1] |
00000000 xxxxyyyy yyzzzzzz |
1110xxxx(E0-EF) 10yyyyyy 10zzzzzz |
第一個字節(jié)由1110開始,接著的字節(jié)由10開始 |
四個x;四個y;二個y;六個z |
四個x;六個y;六個z |
010000 - 10FFFF 1048576個代碼 |
000wwwxx xxxxyyyy yyzzzzzz |
11110www(F0-F4) 10xxxxxx 10yyyyyy 10zzzzzz |
由11110開始,接著的字節(jié)由10開始 |
三個w;二個x;四個x;四個y;二個y;六個z |
三個w;六個x;六個y;六個z |
- Note 1 Unicode在范圍D800-DFFF中不存在任何字符,基本多文種平面中約定了這個范圍用于UTF-16擴展標(biāo)識輔助平面(兩個UTF-16表示一個輔助平面字符)。當(dāng)然,任何編碼都是可以被轉(zhuǎn)換到這個范圍,但在unicode中他們并不代表任何合法的值。
以上這個表是php截取utf-8字符串的關(guān)鍵,根據(jù)每個字節(jié)的前幾位的數(shù)字決定該字符占幾個字節(jié)(utf-8的編碼有點類似于5類IP地址的編碼)
例如,希伯來語字母 aleph(א)的Unicode代碼是 U+05D0,按照以下方法改成 UTF-8:
- 它屬于 U+0080到U+07FF區(qū)域,這個表說明它使用雙字節(jié),110yyyyy 10zzzzzz.
- 十六進制 的 0x05D0換算成二進制就是 101-1101-0000.
- 這11位數(shù)按順序放入"y"部分和"z"部分:11010111 10010000.
- 最后結(jié)果就是雙字節(jié),用十六進制寫起來就是 0xD7 0x90,這就是這個字符aleph(א)的UTF-8編碼。
所以開始的128個字符(US-ASCII)只需一字節(jié),接下來的1920個字符需要雙字節(jié)編碼,包括帶附加符號的拉丁字母,希臘字母,西里爾字母,科普特語字母,亞美尼亞語字母,希伯來文字母和阿拉伯字母的字符。基本多文種平面中其余的字符使用三個字節(jié),剩余字符使用四個字節(jié)。
設(shè)計UTF-8的理由(utf-8的特點)
UTF-8的設(shè)計有以下的多字符組序列的特質(zhì):
- 單字節(jié)字符的最高有效位元永遠(yuǎn)為0。
- 多字節(jié)序列中的首個字符組的幾個最高有效位元決定了序列的長度。最高有效位為
110
的是2字節(jié)序列,而1110
的是三字節(jié)序列,如此類推。
- 多字節(jié)序列中其余的字節(jié)中的首兩個最高有效位元為
10
。
UTF-8的這些特質(zhì),保證了一個字符的字節(jié)序列不會包含在另一個字符的字節(jié)序列中。這確保了以字節(jié)為基礎(chǔ)的部份字串比對(sub-string match)方法可以適用于在文字中搜尋字或詞。有些比較舊的可變長度8位元編碼(如Shift JIS)沒有這個特質(zhì),故字串比對的算法變得相當(dāng)復(fù)雜。雖然這增加了UTF-8編碼的字串的信息冗余,但是利多于弊。另外,資料壓縮并非Unicode 的目的,所以不可混為一談。即使在傳送過程中有部份字節(jié)因錯誤或干擾而完全遺失,還是有可能在下一個字符的起點重新同步,令受損范圍受到限制。
另一方面,由于其字節(jié)序列設(shè)計,如果一個疑似為字符串的序列被驗證為UTF-8編碼,那么我們可以有把握地說它是UTF-8字符串。一段兩字節(jié)隨機序列碰巧為合法的UTF-8而非ASCII 的機率為32分1。對于三字節(jié)序列的機率為256分3,對更長的序列的機率就更低了。
-
- 在ASCII碼的范圍,用一個字節(jié)表示,超出ASCII碼的范圍就用字節(jié)表示,這就形成了我們上面看到的UTF-8的表示方法,這様?shù)暮锰幨钱?dāng)UNICODE文件中只有ASCII碼時,儲存的文件都為一個字節(jié),所以就是普通的ASCII文件無異,讀取的時候也是如此,所以能與以前的ASCII文件相容。
-
- 大于ASCII碼的,就會由上面的第一字節(jié)的前幾位表示該unicode字符的長度,比如110xxxxxx前三位的二進制表示告訴我們這是個 2BYTE的UNICODE字符;1110xxxx是個三位的UNICODE字符,依此類推;xxx 的位置由字符編碼數(shù)的二進制表示的位填入。越靠右的 x 具有越少的特殊意義。只用最短的那個足夠表達(dá)一個字符編碼數(shù)的多字節(jié)串。注意在多字節(jié)串中,第一個字節(jié)的開頭"1"的數(shù)目就是整個串中字節(jié)的數(shù)目。。
utf-8的特性
- UCS 字符 U+0000 到 U+007F (ASCII) 被編碼為字節(jié) 0x00 到 0x7F(ASCII 兼容),這也意味著只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 兩種編碼方式下是一樣的。
- 所有 >U+007F 的 UCS 字符被編碼為一個多個字節(jié)的串,每個字節(jié)都有標(biāo)記位集。因此,ASCII 字節(jié) (0x00-0x7F) 不可能作為任何其他字符的一部分。
- 表示非 ASCII 字符的多字節(jié)串的第一個字節(jié)總是在 0xC0 到 0xFD 的范圍里,并指出這個字符包含多少個字節(jié)。多字節(jié)串的其余字節(jié)都在 0x80 到 0xBF 范圍里,這使得重新同步非常容易,并使編碼無國界,且很少受丟失字節(jié)的影響。
- 可以編入所有可能的 231個 UCS 代碼
- UTF-8 編碼字符理論上可以最多到 6 個字節(jié)長,然而 16 位 BMP 字符最多只用到 3 字節(jié)長。
- Bigendian UCS-4 字節(jié)串的排列順序是預(yù)定的。
- 字節(jié) 0xFE 和 0xFF 在 UTF-8 編碼中從未用到,同時,UTF-8以字節(jié)為編碼單元,它的字節(jié)順序在所有系統(tǒng)中都是一様?shù)?,沒有字節(jié)序的問題,也因此它實際上并不需要BOM。
- 與 UTF-16 或其他 Unicode 編碼相比,對于不支援 Unicode 和 XML 的系統(tǒng),UTF-8 更不容易造成問題。
gb18030
與GB 2312-1980完全兼容,與GBK基本兼容,支持GB 13000及Unicode的全部統(tǒng)一漢字,共收錄漢字70244個。
GB 18030主要有以下特點:
- 采用多字節(jié)編碼,每個字可以由1個、2個或4個字節(jié)組成。(變長編碼)
- 編碼空間龐大,最多可定義161萬個字符。
- 支持中國國內(nèi)少數(shù)民族的文字,不需要動用造字區(qū)。
字節(jié)結(jié)構(gòu)
- 單字節(jié),其值從0到0x7F。
- 雙字節(jié),第一個字節(jié)的值從0x81到0xFE,第二個字節(jié)的值從0x40到0xFE(不包括0x7F)。
- 四字節(jié),第一個字節(jié)的值從0x81到0xFE,第二個字節(jié)的值從0x30到0x39,第三個字節(jié)從0x81到0xFE,第四個字節(jié)從0x30到0x39。
gb2312
GB2312編碼通行于中國大陸;新加坡等地也采用此編碼。中國大陸幾乎所有的中文系統(tǒng)和國際化的軟件都支持GB 2312。
GB 2312標(biāo)準(zhǔn)共收錄6763個漢字,其中一級漢字3755個,二級漢字3008個;同時,GB 2312收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西里爾字母在內(nèi)的682個全角字符。
GB 2312的出現(xiàn),基本滿足了漢字的計算機處理需要,它所收錄的漢字已經(jīng)覆蓋中國大陸99.75%的使用頻率。
對于人名、古漢語等方面出現(xiàn)的罕用字,GB 2312不能處理,這導(dǎo)致了后來GBK及GB 18030漢字字符集的出現(xiàn)。
GB 2312中對所收漢字進行了“分區(qū)”處理,每區(qū)含有94個漢字/符號。這種表示方式也稱為區(qū)位碼。
- 01-09區(qū)為特殊符號。
- 16-55區(qū)為一級漢字,按拼音排序。
- 56-87區(qū)為二級漢字,按部首/筆畫排序。
10-15區(qū)及88-94區(qū)則未有編碼。
舉例來說,“啊”字是GB2312之中的第一個漢字,它的區(qū)位碼就是1601。
字節(jié)結(jié)構(gòu)
在使用GB2312的程序中,通常采用EUC儲存方法,以便兼容于ASCII。瀏覽器編碼表上的“GB2312”,通常都是指“EUC-CN”表示法。
每個漢字及符號以兩個字節(jié)來表示。第一個字節(jié)稱為“高位字節(jié)”,第二個字節(jié)稱為“低位字節(jié)”。
“高位字節(jié)”使用了0xA1-0xF7(把01-87區(qū)的區(qū)號加上0xA0),“低位字節(jié)”使用了0xA1-0xFE(把01-94加上0xA0)。 由于一級漢字從16區(qū)起始,漢字區(qū)的“高位字節(jié)”的范圍是0xB0-0xF7,“低位字節(jié)”的范圍是0xA1-0xFE,占用的碼位是72*94=6768。其中有5個空位是D7FA-D7FE。
例如“啊”字在大多數(shù)程序中,會以兩個字節(jié),0xB0(第一個字節(jié))0xA1(第二個字節(jié))儲存。(與區(qū)位碼對比:0xB0=0xA0+16,0xA1=0xA0+1)。
EUC-CN(網(wǎng)上下到的編碼表就是這個)(gb2312的字符串截取也是按照該表截取的)
EUC-CN是GB 2312最常用的表示方法。瀏覽器編碼表上的“GB2312”,通常都是指“EUC-CN”表示法。
GB 2312字符使用兩個字節(jié)來表示。
- “第一位字節(jié)”使用0xA1-0xF7
- “第二位字節(jié)”使用0xA1-0xFE
舉例來說,“啊”字是GB 2312之中的第一個漢字,它的區(qū)位碼是1601。
在EUC-CN之中,它把0xA0+16=0xB0,0xA0+1=0xA1,得出0xB0A1。
您可能感興趣的文章:- Python實現(xiàn)把utf-8格式的文件轉(zhuǎn)換成gbk格式的文件
- 趣談Unicode、Ascii、utf-8、GB2312、GBK等編碼知識
- Shell腳本把文件從GBK轉(zhuǎn)為UTF-8編碼
- PHP 正則判斷中文UTF-8或GBK的思路及具體實現(xiàn)
- 字符編碼詳解及由來(UNICODE,UTF-8,GBK) 比較詳細(xì)
- UTF-8 GBK UTF8 GB2312 之間的區(qū)別和關(guān)系介紹
- 常用字符集編碼詳解(ASCII GB2312 GBK GB18030 unicode UTF-8)
- 首頁四格,首頁五格For6.0(GBK)(UTF-8)[12種組合][9-18][版主安裝測試通過]
- MySQL GBK→UTF-8編碼轉(zhuǎn)換
- Java gbk轉(zhuǎn)utf-8