原文鏈接:
https://www.xuebuyuan.com/1560869.html?mobile=1
侵刪。
參考文檔:
https://baike.baidu.com/view/443268.htm?fromId=25492
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
http://tech.idv2.com/2008/02/21/unicode-intro/
https://baike.baidu.com/view/185282.htm
https://baike.baidu.com/view/40801.htm
http://hilojack.sinaapp.com/?p=1291
ASCII
1. ASCII碼只表示128個字符,最前面一位爲0. ASCII是計算機的一個基礎存儲格式。其他存儲格式也都爲它做了預留。
Unicode與UCS2\UTF8\UTF16
1. Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。UCS-2用兩個字節編碼,UCS-4用4個字節編碼。
我們通常Windows上見到的Unicode,不做說明的情況下,都是指的UCS-2這種字節編碼。
2. Unicode UCS2使用兩個字節來存儲,是我們大多數情況都用到的uniocde方式,代碼中使用也很方便(w_char)-雙字節與它直接對應起來了。
3. UTF8使用的也非常普遍,它也是一種unicode的編碼格式,它存在1/2/3/4個字節來表示一個文字。對於英文字符來說,使用空間非常小。
4. UCS2與UTF16: UCS-2是UTF-16的子集,僅支持Unicode字符平面映射中的基本多文平面.佔2個字節. 參考:http://hilojack.sinaapp.com/?p=1291
ANSI與GB2312
1. ANSI: unicode和ansi都是字符代碼的一種表示形式,使用1-2字節表示一個字符。ANSI爲使計算機支持更多語言,通常使用 0x80~0xFF 範圍的 2 個字節來表示 1 個字符。不同的國家和地區制定了不同的標準,由此產生了 GB2312, BIG5, JIS 等各自的編碼標準。
2. GB2312是一種本地化的編碼格式,是ANSI字符代碼的一種編碼格式,相同的值,在其他本地語言體系裏,表達的東西是不同的。《信息交換用漢字編碼字符集》是由中國國家標準總局1980年發佈,1981年5月1日開始實施的一套國家標準,標準號是GB 2312—1980。
參考:https://baike.baidu.com/view/443268.htm?fromId=25492
下面爲轉載內容:地址如下
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
-------------------------------------------------------------
字符編碼筆記:ASCII,Unicode和UTF-8
作者:
阮一峯
今天中午,我突然想搞清楚Unicode和UTF-8之間的關係,於是就開始在網上查資料。
結果,這個問題比我想象的複雜,從午飯後一直看到晚上9點,纔算初步搞清楚。
下面就是我的筆記,主要用來整理自己的思路。但是,我儘量試圖寫得通俗易懂,希望能對其他朋友有用。畢竟,字符編碼是計算機技術的基石,想要熟練使用計算機,就必須懂得一點字符編碼的知識。
1. ASCII碼
我們知道,在計算機內部,所有的信息最終都表示爲一個二進制的字符串。每一個二進制位(bit)有0和1兩種狀態,因此八個二進制位就可以組合出256種狀態,這被稱爲一個字節(byte)。也就是說,一個字節一共可以用來表示256種不同的狀態,每一個狀態對應一個符號,就是256個符號,從0000000到11111111。
上個世紀60年代,美國製定了一套字符編碼,對英語字符與二進制位之間的關係,做了統一規定。這被稱爲ASCII碼,一直沿用至今。
ASCII碼一共規定了128個字符的編碼,比如空格"SPACE"是32(二進制00100000),大寫的字母A是65(二進制01000001)。這128個符號(包括32個不能打印出來的控制符號),只佔用了一個字節的後面7位,最前面的1位統一規定爲0。
2、非ASCII編碼
英語用128個符號編碼就夠了,但是用來表示其他語言,128個符號是不夠的。比如,在法語中,字母上方有注音符號,它就無法用ASCII碼錶示。於是,一些歐洲國家就決定,利用字節中閒置的最高位編入新的符號。比如,法語中的é的編碼爲130(二進制10000010)。這樣一來,這些歐洲國家使用的編碼體系,可以表示最多256個符號。
但是,這裏又出現了新的問題。不同的國家有不同的字母,因此,哪怕它們都使用256個符號的編碼方式,代表的字母卻不一樣。比如,130在法語編碼中代表了é,在希伯來語編碼中卻代表了字母Gimel (ג),在俄語編碼中又會代表另一個符號。但是不管怎樣,所有這些編碼方式中,0--127表示的符號是一樣的,不一樣的只是128--255的這一段。
至於亞洲國家的文字,使用的符號就更多了,漢字就多達10萬左右。一個字節只能表示256種符號,肯定是不夠的,就必須使用多個字節表達一個符號。比如,簡體中文常見的編碼方式是GB2312,使用兩個字節表示一個漢字,所以理論上最多可以表示256x256=65536個符號。
中文編碼的問題需要專文討論,這篇筆記不涉及。這裏只指出,雖然都是用多個字節表示一個符號,但是GB類的漢字編碼與後文的Unicode和UTF-8是毫無關係的。
3.Unicode
正如上一節所說,世界上存在着多種編碼方式,同一個二進制數字可以被解釋成不同的符號。因此,要想打開一個文本文件,就必須知道它的編碼方式,否則用錯誤的編碼方式解讀,就會出現亂碼。爲什麼電子郵件常常出現亂碼?就是因爲發信人和收信人使用的編碼方式不一樣。
可以想象,如果有一種編碼,將世界上所有的符號都納入其中。每一個符號都給予一個獨一無二的編碼,那麼亂碼問題就會消失。這就是Unicode,就像它的名字都表示的,這是一種所有符號的編碼。
Unicode當然是一個很大的集合,現在的規模可以容納100多萬個符號。每個符號的編碼都不一樣,比如,U+0639表示阿拉伯字母Ain,U+0041表示英語的大寫字母A,U+4E25表示漢字"嚴"。具體的符號對應表,可以查詢unicode.org,或者專門的漢字對應表。
4. Unicode的問題
需要注意的是,Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。
比如,漢字"嚴"的unicode是十六進制數4E25,轉換成二進制數足足有15位(100111000100101),也就是說這個符號的表示至少需要2個字節。表示其他更大的符號,可能需要3個字節或者4個字節,甚至更多。
這裏就有兩個嚴重的問題,第一個問題是,如何才能區別Unicode和ASCII?計算機怎麼知道三個字節表示一個符號,而不是分別表示三個符號呢?第二個問題是,我們已經知道,英文字母只用一個字節表示就夠了,如果Unicode統一規定,每個符號用三個或四個字節表示,那麼每個英文字母前都必然有二到三個字節是0,這對於存儲來說是極大的浪費,文本文件的大小會因此大出二三倍,這是無法接受的。
它們造成的結果是:1)出現了Unicode的多種存儲方式,也就是說有許多種不同的二進制格式,可以用來表示Unicode。2)Unicode在很長一段時間內無法推廣,直到互聯網的出現。
5.UTF-8
互聯網的普及,強烈要求出現一種統一的編碼方式。UTF-8就是在互聯網上使用最廣的一種Unicode的實現方式。其他實現方式還包括UTF-16(字符用兩個字節或四個字節表示)和UTF-32(字符用四個字節表示),不過在互聯網上基本不用。重複一遍,這裏的關係是,UTF-8是Unicode的實現方式之一。
UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。
UTF-8的編碼規則很簡單,只有二條:
1)對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
2)對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一律設爲10。剩下的沒有提及的二進制位,全部爲這個符號的unicode碼。
下表總結了編碼規則,字母x表示可用編碼的位。
Unicode符號範圍 | UTF-8編碼方式
(十六進制) | (二進制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
下面,還是以漢字"嚴"爲例,演示如何實現UTF-8編碼。
已知"嚴"的unicode是4E25(100111000100101),根據上表,可以發現4E25處在第三行的範圍內(0000 0800-0000 FFFF),因此"嚴"的UTF-8編碼需要三個字節,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然後,從"嚴"的最後一個二進制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就得到了,"嚴"的UTF-8編碼是"11100100 10111000 10100101",轉換成十六進制就是E4B8A5。
6. Unicode與UTF-8之間的轉換
通過上一節的例子,可以看到"嚴"的Unicode碼是4E25,UTF-8編碼是E4B8A5,兩者是不一樣的。它們之間的轉換可以通過程序實現。
在Windows平臺下,有一個最簡單的轉化方法,就是使用內置的記事本小程序Notepad.exe。打開文件後,點擊"文件"菜單中的"另存爲"命令,會跳出一個對話框,在最底部有一個"編碼"的下拉條。
裏面有四個選項:ANSI,Unicode,Unicode big endian 和 UTF-8。
1)ANSI是默認的編碼方式。對於英文文件是ASCII編碼,對於簡體中文文件是GB2312編碼(只針對Windows簡體中文版,如果是繁體中文版會採用Big5碼)。
2)Unicode編碼指的是UCS-2編碼方式,即直接用兩個字節存入字符的Unicode碼。這個選項用的little endian格式。
3)Unicode big endian編碼與上一個選項相對應。我在下一節會解釋little endian和big endian的涵義。
4)UTF-8編碼,也就是上一節談到的編碼方法。
選擇完"編碼方式"後,點擊"保存"按鈕,文件的編碼方式就立刻轉換好了。
7. Little endian和Big endian
上一節已經提到,Unicode碼可以採用UCS-2格式直接存儲。以漢字"嚴"爲例,Unicode碼是4E25,需要用兩個字節存儲,一個字節是4E,另一個字節是25。存儲的時候,4E在前,25在後,就是Big endian方式;25在前,4E在後,就是Little endian方式。
這兩個古怪的名稱來自英國作家斯威夫特的《格列佛遊記》。在該書中,小人國裏爆發了內戰,戰爭起因是人們爭論,吃雞蛋時究竟是從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開。爲了這件事情,前後爆發了六次戰爭,一個皇帝送了命,另一個皇帝丟了王位。
因此,第一個字節在前,就是"大頭方式"(Big endian),第二個字節在前就是"小頭方式"(Little endian)。
那麼很自然的,就會出現一個問題:計算機怎麼知道某一個文件到底採用哪一種方式編碼?
Unicode規範中定義,每一個文件的最前面分別加入一個表示編碼順序的字符,這個字符的名字叫做"零寬度非換行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。這正好是兩個字節,而且FF比FE大1。
如果一個文本文件的頭兩個字節是FE FF,就表示該文件採用大頭方式;如果頭兩個字節是FF FE,就表示該文件採用小頭方式。
8. 實例
下面,舉一個實例。
打開"記事本"程序Notepad.exe,新建一個文本文件,內容就是一個"嚴"字,依次採用ANSI,Unicode,Unicode big endian 和 UTF-8編碼方式保存。
然後,用文本編輯軟件UltraEdit中的"十六進制功能",觀察該文件的內部編碼方式。
1)ANSI:文件的編碼就是兩個字節"D1 CF",這正是"嚴"的GB2312編碼,這也暗示GB2312是採用大頭方式存儲的。
2)Unicode:編碼是四個字節"FF FE 25 4E",其中"FF FE"表明是小頭方式存儲,真正的編碼是4E25。
3)Unicode big endian:編碼是四個字節"FE FF 4E 25",其中"FE FF"表明是大頭方式存儲。
4)UTF-8:編碼是六個字節"EF BB BF E4 B8 A5",前三個字節"EF BB BF"表示這是UTF-8編碼,後三個"E4B8A5"就是"嚴"的具體編碼,它的存儲順序與編碼順序是一致的。
9. 延伸閱讀
*
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets(關於字符集的最基本知識)
*
RFC3629:UTF-8, a transformation format of ISO 10646(如果實現UTF-8的規定)
以下是轉載內容,轉載地址:
http://hilojack.sinaapp.com/?p=1291
-----------------------------------------------------------------------------
04 五 13
字符編碼入門
序
本文試圖理清字符編碼系統的整體結構.如有理解不對請指正.
字符編碼
按照[現代的編碼模型],字符編碼的主要概念分爲:有哪些字符(字符表)、它們的編號(編碼字符集)、這些編號如何編碼成一系列的“碼元”(字符編碼表)、這些碼元如何組成八位字節流(字符編碼方案).
字符表(Character Repotire)
一個系統所有抽象字符的集合,包括我們看得見的漢字/數字/符號和看不見的控制字符.unicode系統所使用的字符集是通用字符集UCS ,由ISO 10646所定義.
編碼字符集(CCS:Coded Character Set)
將字符集C映射到非負整數(碼位:編碼字符的位置).如unicode字符平面映射.即完成對字符的編號.
unicode系統中的碼位也叫unicode編碼.
字符編碼表(CEF:Caracter Encoding Form)
將碼位轉換成有限比特長度的整數值(碼元/碼值:字符編碼的值)
在unicode系統中,其碼位可被轉換成8位串行的UTF-8,或者16位串行的UTF-16等等.也就說同一碼位對應多個碼值.
碼元(Code Unit,也稱“代碼單元”)是指一個已編碼的文本中具有最短的比特組合的單元。對於UTF-8來說,碼元是8比特長;對於UTF-16來說,碼元是16比特長;對於UTF-32來說,碼元是32比特長。編碼長度是碼元的整數倍,如UTF-16的長度就是2字節/4字節(一對碼元)
我們平時所說的UTF-8,UTF-16都處於字符編碼表(CEF)的層面.
字符編碼方案(CES:Caracter Encodeing Scheme)
定義如何將碼值對應到8位組的串行,以便網絡傳輸和文件存儲.
這裏有兩個大背景:
- 對於多字節的UTF-16來說,windows是先讀高字節再讀低字節,而MAC則相反.爲了標識字節順序,就選擇了一個字節序列標記(BOM:Byte Order Mark)來指定大端序(UTF-16 BE)和小端序(UTF-16).見UTF-16的編碼模式
- 有些複雜的編碼需要特別的方案:如ISO/IEC 2022需要使用轉義串行,如SCSU、BOCU和Punycode需要壓縮
在vim中,:%xxd 可查看相關字符的編碼 :set fileencoding=**可對字符進行編碼轉換
unicode編碼體系
unicode又名統一碼、萬國碼、單一碼、標準萬國碼
意義
因多語言環境的需要而誕生,它對應於ISO 10646通用字符集UCS,包括了其它所有字符集/已知語言的所有字符.
unicode與iso 10646
史上存在兩個嘗試創立單一字符集的組織:
- 國際標準化組織ISO——開發了ISO/IEC 10646項目
- 統一碼聯盟Unicode Consortium——開發了統一碼項目
1991年前後,兩個項目的參與者都認識到,世界不需要兩個不兼容的字符集。於是,它們開始合併雙方的工作成果,併爲創立一個單一編碼表而協同工作.
到現在兩個項目仍都存在,兩者使用同一字符集,但二者本質上是不同的標準——unicode標準更爲豐富,它額外定義了許多與字符相關的語義符號學,並且部分樣例字形與iso 10646有顯著區別。
unicode的編碼和實現
一般,unicode編碼系統分爲編碼方式(CCS)和實現方式(CEF/CES …).
unicode編碼方式(CCS)
統一碼(unicode)的編碼方式使用的是通用字符集UCS. unicode字符的平面映射本質上就是CCS碼位映射,即對字符的編號(ISO/IEC 10646-1所定義)
(CCS)
這個碼位就叫unicode編碼.
- UCS-2:包含字符平面映射中的基本多文種平面,佔16位,可表達2^16=65536個字符.2. UCS-4:其中已經定義了16個輔助平面.標準規定的UCS-4會佔用32個字節,最高字節恆爲0,可表達2^31個字符.
平面 | 始末字符值 | 中文名稱 | 英文名稱 |
---|---|---|---|
0號平面 | U+0000 – U+FFFF | 基本多文種平面 | Basic Multilingual Plane, 簡稱 BMP |
1號平面 | U+10000 – U+1FFFF | 多文種補充平面 | Supplementary Multilingual Plane, 簡稱 SMP |
2號平面 | U+20000 – U+2FFFF | 表意文字補充平面 | Supplementary Ideographic Plane, 簡稱 SIP |
3號平面 | U+30000 – U+3FFFF | 表意文字第三平面(未正式使用[1]) | Tertiary Ideographic Plane, 簡稱 TIP |
4號平面 至 13號平面 |
U+40000 – U+DFFFF | (尚未使用) | |
14號平面 | U+E0000 – U+EFFFF | 特別用途補充平面 | Supplementary Special-purpose Plane, 簡稱 SSP |
15號平面 | U+F0000 – U+FFFFF | 保留作爲私人使用區(A區)[2] | Private Use Area-A, 簡稱 PUA-A |
16號平面 | U+100000 – U+10FFFF | 保留作爲私人使用區(B區)[2] | Private Use Area-B, 簡稱 PUA-B |
實現方式(CEF/CES …)
在unicode編碼體系中unicode碼位轉爲實際存儲的編碼(碼值)可以有不同實現方式.比如UTF8/UTF-16/UTF-32
在unicode體系中碼位是唯一的,所以字符編碼轉換程序 在轉碼時 一般把碼值轉爲unicode再轉爲其它的編碼.
字節順序標記(BOM)
BOM是用來標記字節序的. 在windows/mac中,UTF-16高低字節的存儲順序是不同的,爲了以示區別,特別定義的大尾序和小尾序.同時在文件頭部加入一個BOM頭(Byte Order Mark).
對於UTF-8來說,它只是一個UTF-8編碼記號(不建議使用,它會干擾很多程序的執行)
建議在編輯器中取消bom,比如在vim設置:set nobomb
編碼 | 表示 (十六進制) | 表示 (十進制) |
---|---|---|
UTF-8 | EF BB BF |
239 187 191 |
UTF-16(大端序) | FE FF |
254 255 |
UTF-16(小端序) | FF FE |
255 254 |
UTF-32(大端序) | 00 00 FE FF |
0 0 254 255 |
UTF-32(小端序) | FF FE 00 00 |
255 254 0 0 |
UTF-7 | 2B 2F 76 和以下的一個字節:[ 38 | 39 | 2B | 2F ] |
43 47 118 和以下的一個字節:[ 56 | 57 | 43 | 47 ] |
en:UTF-1 | F7 64 4C |
247 100 76 |
en:UTF-EBCDIC | DD 73 66 73 |
221 115 102 115 |
en:Standard Compression Scheme for Unicode | 0E FE FF |
14 254 255 |
en:BOCU-1 | FB EE 28 及可能跟隨着FF |
251 238 40 及可能跟隨着255 |
GB-18030 | 84 31 95 33 |
132 49 149 51 |
使用UTF-16編碼的例子 | ||||||
---|---|---|---|---|---|---|
編碼名稱 | 編碼次序 | 編碼 | ||||
BOM | 朱 | , | 聿 | |||
UTF-16LE | 小尾序 | 31 67 | 2C 00 | 7F 80 | 69 D8 A5 DE | |
UTF-16BE | 大尾序 | 67 31 | 00 2C | 80 7F | D8 69 DE A5 | |
UTF-16 | 小尾序,包含BOM | FF FE | 31 67 | 2C 00 | 7F 80 | 69 D8 A5 DE |
UTF-16 | 大尾序,包含BOM | FE FF | 67 31 | 00 2C | 80 7F | D8 69 DE A5 |
UTF-16/UCS-2
UTF-16是Unicode字符集的一種轉換方式(Unicode Transfomation Format),它把unicode碼位轉爲16比特長的碼元.
字符長度:2個字節(16比特),4個字節(一對16比特碼元)
UCS-2是UTF-16的子集,僅支持Unicode字符平面映射中的基本多文平面.佔2個字節.
字符編碼表(CEF)
對於unicoe基本多文平面(0×0000~0xffff).UTF-16的編碼爲一個16比特:
UTF-16 == Unicode(0x0~0xffff) #不含(0xd800~0xdfff),這個區保留給UTF-16的前導代理和後導代理
對於uncide輔助平面(0×10000~0x10ffff),UTF-16的編碼爲一對16比特字符串,由前導代理(lead surrogates)和後導代理(trail surrogates)組成.
將unicode碼元(0x10000~0x10ffff)減去0x10000得到20位比特:0x0~0xfffff,這20位比特分高10位A(0~0x3ff)和低10位B(0~0x3ff)
UTF-16(lead surrogates) == A+0xd800 #值範圍(0xd800~0xdbff)
UTF-16(trail surrogates) == B+0xd800 #值範圍(0xdc00~0xdfff)
UTF-16字符匹配正則
根據UTF-16的CEF規則,我們可以得到關於匹配UTF-16字符的正則僞代碼(這個正則是無法執行的,可執行的正則可比這個可複雜多了):
'#[\x{0000}-\x{d7ff}]
|[\x{e000}-\x{ffff}]
|([\x{d800}-\x{dbff}][\x{dc00}-\x{dfff}])#'
UTF-8
utf8以8位爲單元對UCS進行編碼,編碼會佔用1~4字節.與utf16所編碼的英文字符相比,它的編碼長度減少一半.
UTF-8 字符編碼表CEF
代碼範圍 十六進制 |
標量值(scalar value) 二進制 |
UTF-8 二進制/十六進制 |
註釋 |
---|---|---|---|
000000 – 00007F 128個代碼 |
00000000 00000000 0zzzzzzz | 0zzzzzzz(00-7F) | ASCII字符範圍,字節由零開始 |
七個z | 七個z | ||
000080 – 0007FF 1920個代碼 |
00000000 00000yyy yyzzzzzz | 110yyyyy(C0-DF) 10zzzzzz(80-BF) | 第一個字節由110開始,接着的字節由10開始 |
三個y;二個y;六個z | 五個y;六個z | ||
000800 – 00D7FF 00E000 – 00FFFF 61440個代碼 [Note 1] |
00000000 xxxxyyyy yyzzzzzz | 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz | 第一個字節由1110開始,接着的字節由10開始 |
四個x;四個y;二個y;六個z | 四個x;六個y;六個z | ||
010000 – 10FFFF 1048576個代碼 |
000wwwxx xxxxyyyy yyzzzzzz | 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz | 將由11110開始,接着的字節由10開始 |
三個w;二個x;四個x;四個y;二個y;六個z | 三個w;六個x;六個y;六個z |
UTF-8優缺點
優點
- 保證搜索時一個字符的字符串不會出現在另一個字符的串裏面.
- 兼容ASCII
- 抗干擾和穩定性好:一段兩字節隨機串行碰巧爲合法的UTF-8而非ASCII的機率爲32分1。對於三字節串行的機率爲256分1,對更長的串行的機率就更低了
缺點
- 與UTF-16/gbk 想比,處理CJK字符串,編碼長度不佔優勢
UTF-8正則匹配
當使用Perl時,可用以下的表達式測試頁面是否使用了UTF-8編碼:
m/\A(
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*\z/x;
utf8_unicode_ci和utf8_general_ci區別
utf8_unicode_ci的最主要的特色是支持擴展,即當把一個字母看作與其它字母組合相等時。例如,在德語和一些其它語言中‘ß’等於‘ss’。
utf8_general_ci是一個遺留的 校對規則,不支持擴展。它僅能夠在字符之間進行逐個比較。這意味着utf8_general_ci校對規則進行的比較速度很快,但是與使用utf8_unicode_ci的校對規則相比,比較正確性較差)。
其它UTF
UTF-7
UTF-7是一種可變長度的字符編碼方式,用以將UTF-16字符以ASCII編碼.也就是說用修改的Base64(Modified Base64)去編碼UTF-16字符.
因爲SMTP作爲基本郵件傳輸標準,只允許傳輸ASCII字符,過去很多郵件傳輸都使用UTF-7.自從MIME擴展了電子郵件標準之後,SMTP支持了其它字符集.現在絕大多數郵件服務商都使用UTF-8/GB2312/GB18030作爲郵件字符編碼.
嚴格來說 UTF-7 不能算是 Unicode 所定義的字符集之一,較精確的來說, UTF-7 是提供了一種將 Unicode 轉換爲 7 比特 US-ASCII 字符的轉換方式
Modified Base64 與Base64的主要區別是結尾不會有”=”
UTF-7由於安全性薄弱,已經走入歷史.
Gmail中文用戶默認外發郵件編碼(content-type)是GB2312(可改爲UTF-8).其傳輸編碼(Content-Transfer-Encoding)會按數據最短的原則選擇: quoted-printable/base64或者不用.
騰訊郵箱用戶默認的外發郵件編碼是gb18030(可改爲UTF-8).其傳輸編碼使用的是base64.
UTF-32
UTF-32 是一個 UCS-4 的子集,使用32-比特的碼值,只在0到10FFFF的字碼空間(百萬個碼位)
內容傳輸編碼(Content-Transfer-Encoding)
CTE由MIME定義,用於email數據傳輸.包括“7bit”,“8bit”,“binary”,“quoted-printable”,“base64”.其中常見的傳輸碼爲Base64/quoted-printable
Base64
Base64不是字符編碼方案,而是一種基於64個可打印字符來表示二進制數據的表示方法.6bit(2^6=64)爲一單元,對應一個可打印的字符.三個字節有24個位元.對應4個Base64字符.
編碼規則
將二進制流/文本流以每6bit爲一單元,3個字節爲一組.以6bit(2^6=64)的數字大小爲位置對應以下字符中的一個:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
如果最後剩餘2個或1個字節,按以下方式補0:
文本 | M | a | n | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ASCII編碼 | 77 | 97 | 110 | |||||||||||||||||||||
二進制位 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 |
索引 | 19 | 22 | 5 | 46 | ||||||||||||||||||||
Base64編碼 | T | W | F | u |
最後,如果剩下兩個字節,在編碼結果後加1個“=”;如果最後剩下一個字節,編碼結果後加2個“=”;如果沒有剩下任何數據,就什麼都不要加,這樣纔可以保證資料還原的正確性。
Quoted-printable
可打印字符引用編碼(Quoted-printable,或QP encoding).
它使用ASCII字符表示各種字符編碼–以便能個7bit or 8bit 數據通路上傳輸數據.
此編碼爲是MIME中 content transfer encoding的一種,用於email.(與base64並列爲兩種基本的郵件傳輸編碼)
編碼規則
Quoted-printable以8bit爲單位進行編碼,規則如下:
一般的8bit編碼爲"="加兩個十六進制值,如"\x7A"編碼爲"=7A"
對於可打印的ascii碼:0x21-0x7E("="號:0x3D除外),可用ASCII碼直接表示
但是,如果水平製表符和空格符出現在行尾,必須用OP編碼表示爲"=09"(tab)和"=20"(space)
如果QP編碼的數據每行長度超過76個字符,QP編碼結果的每行結尾加一個軟換行("=")
Gmail在發送以下字符時所使用的Content-Transfer-Econding正是QP,如果將其ContentType設置爲:UTF-8.併發送郵件內容(“新”的utf8編碼爲\xe696b0):
新This is a test!
If you believe that truth=beauty, then surely mathematics is the most beautiful branch of philosophy.
那麼,經過QP編碼後的郵件text/plain原文爲:
=E6=96=B0This is a test!
If you believe that truth=3Dbeauty, then surely mathematics is the most bea=
utiful branch of philosophy.
你很可能看到的是這個(因爲你的郵件文本編輯器做format字符時就在most處斷行了,使得單行不超過76個字符):
=E6=96=B0This is a test!
If you believe that truth=3Dbeauty, then surely mathematics is the most
beautiful branch of philosophy.
還有一個text/html原文.
與base64相比,如果Content-Type編碼與ASCII是兼容的,那麼QP編碼後的郵件原文中ASCII是可讀的.
GB相關的編碼
本小節主要歸納漢字相關的編碼:GB2312,GBK,GB18030.他們的關係如下圖:
如圖所示,GB18030基本兼容GBK.
GB2312
GB2312,也叫GB2312-80,於1981年推出.
特點
- 收錄6763個漢字
編碼結構
先對漢字進行分區(得到的編碼叫區位碼).
- 01-09區爲特殊符號。
- 16-55區爲一級漢字,按拼音排序。
- 56-87區爲二級漢字,按部首/筆畫排序。
編碼:
對於ascii(0×00-0x7f)保持不變.
對於漢字和符號,使用兩個字節表示:“高位字節”使用了0xA1-0xF7(把01-87區的區號加上0xA0),“低位字節”使用了0xA1-0xFE(把01-94加上0xA0)
“啊”的區位碼是0×1001,對應的gb2312就是0xb0a1
GBK
背景
因爲原GB2312字符不足, 廠商微軟利用GB 2312-80未使用的編碼空間,收錄GB 13000.1-93全部字符制定了GBK編碼.
編碼結構
對於GB2312字符保持不變,僅對Gb2312未使用的編碼區進行了擴充.
對於雙字節來說:第一字節的範圍是81–FE(也就是不含80和FF),第二字節的一部分領域在40–7E,其他領域在80–FE.
範圍 | 第1字節 | 第2字節 | 編碼數 | 字數 |
---|---|---|---|---|
水準 GBK/1 | A1 –A9 |
A1 –FE |
846 | 717 |
水準 GBK/2 | B0 –F7 |
A1 –FE |
6,768 | 6,763 |
水準 GBK/3 | 81 –A0 |
40 –FE (7F 除外) |
6,080 | 6,080 |
水準 GBK/4 | AA –FE |
40 –A0 (7F 除外) |
8,160 | 8,160 |
水準 GBK/5 | A8 –A9 |
40 –A0 (7F 除外) |
192 | 166 |
用戶定義 | AA –AF |
A1 –FE |
564 | |
用戶定義 | F8 –FE |
A1 –FE |
658 | |
用戶定義 | A1 –A7 |
40 –A0 (7F 除外) |
672 | |
合計: | 23,940 | 21,886 |
按拼音排序
基於Gbk/Gb2312是按音序來編碼的.可用此規則來對漢字進行拼音排序(以php爲例)
//按拼音首字母排序
$arr = array(
'北京'=>'010',
'成都'=>'028',
);
ukrsort($arr, 'cmp');
var_dump($arr);
/**
*
* 比較拼音首字母(基於字符是按拼音順序編碼)
*/
function cmp(&$a, &$b) {
$a = iconv('utf-8', 'gbk', $a);
$a = $a[0];
$b = iconv('utf-8', 'gbk', $b);
$b = $b[0];
if ($a == $b) {
return 0;
}
return ($a > $b) ? 1 : -1;
}
function ukrsort(&$arr, $func) {
foreach ($arr as $k => $v) {
if (is_array($arr[$k])) {
ukrsort($arr[$k], $func);
}
}
uksort($arr, $func);
}
也可以通過編碼找到絕大部分漢字的拼音首字母(以php爲例)
/**
* 獲取漢字拼音首字母(基於字符是按拼音順序編碼)
*/
function getFirstLetter($str) {
$fchar = ord($str{0});
if ($fchar >= ord("A") and $fchar <= ord("z"))
return strtoupper($str{0});
if (!is_string($str)) {
var_dump($str);
return;
}
$s1 = @iconv("UTF-8", "gbk", $str);
$s2 = @iconv("gbk", "UTF-8", $s1);
if ($s2 == $str) {
$s = $s1;
} else {
$s = $str;
}
$asc = ord($s{0}) * 256 + ord($s{1}) ;
if ($asc >= 45217 and $asc <= 45252)
return "A";
if ($asc >= 45253 and $asc <= 45760)
return "B";
if ($asc >= 45761 and $asc <= 46317)
return "C";
if ($asc >= 46318 and $asc <= 46825)
return "D";
if ($asc >= 46826 and $asc <= 47009)
return "E";
if ($asc >= 47010 and $asc <= 47296)
return "F";
if ($asc >= 47297 and $asc <= 47613)
return "G";
if ($asc >= 47614 and $asc <= 48118)
return "I";
if ($asc >= 48119 and $asc <= 49061)
return "J";
if ($asc >= 49062 and $asc <= 49323)
return "K";
if ($asc >= 49324 and $asc <= 49895)
return "L";
if ($asc >= 49896 and $asc <= 50370)
return "M";
if ($asc >= 50371 and $asc <= 50613)
return "N";
if ($asc >= 50614 and $asc <= 50621)
return "O";
if ($asc >= 50622 and $asc <= 50905)
return "P";
if ($asc >= 50906 and $asc <= 51386)
return "Q";
if ($asc >= 51387 and $asc <= 51445)
return "R";
if ($asc >= 51446 and $asc <= 52217)
return "S";
if ($asc >= 52218 and $asc <= 52697)
return "T";
if ($asc >= 52698 and $asc <= 52979)
return "W";
if ($asc >= 52980 and $asc <= 53688)
return "X";
if ($asc >= 53689 and $asc <= 54480)
return "Y";
if ($asc >= 54481 and $asc <= 55289)
return "Z";
return null;
}
GB18030
GB 18030,全稱:國家標準GB 18030-2005《信息技術 中文編碼字符集》,是中華人民共和國現時最新的內碼字集(2005年發佈).
有以下特點:
採用多字節編碼,每個字可以由1個、2個或4個字節組成。
支持全部unicode(UCS)全部統一漢字.收錄範圍包含繁體漢字以及日韓漢字70244個
與GBK基本兼容,與GB 2312完全兼容
編碼結構
- 單字節,其值從0到0x7F。
- 雙字節,第一個字節的值從0×81到0xFE,第二個字節的值從0×40到0xFE(不包括0x7F)。
- 四字節,第一/三字節的值從0×81到0xFE,第二/四字節的值從0×30到0×39.
正則匹配
'#[\x00-\x7f]|[\x81-\xfe][\x40-0xfe]|([\x81-0xfe][\x30-\x39]){2}#'