文本的編碼格式: ANSI、ASCII、UTF8、UNICODE、GB2312、UCS-2、UTF16

原文鏈接:

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。打開文件後,點擊"文件"菜單中的"另存爲"命令,會跳出一個對話框,在最底部有一個"編碼"的下拉條。

bg2007102801.jpg

裏面有四個選項: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(關於字符集的最基本知識)


談談Unicode編碼


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位組的串行,以便網絡傳輸和文件存儲.
這裏有兩個大背景:

  1. 對於多字節的UTF-16來說,windows是先讀高字節再讀低字節,而MAC則相反.爲了標識字節順序,就選擇了一個字節序列標記(BOM:Byte Order Mark)來指定大端序(UTF-16 BE)和小端序(UTF-16).見UTF-16的編碼模式
  2. 有些複雜的編碼需要特別的方案:如ISO/IEC 2022需要使用轉義串行,如SCSU、BOCU和Punycode需要壓縮

在vim中,:%xxd 可查看相關字符的編碼 :set fileencoding=**可對字符進行編碼轉換

unicode編碼體系

unicode又名統一碼、萬國碼、單一碼、標準萬國碼

意義

因多語言環境的需要而誕生,它對應於ISO 10646通用字符集UCS,包括了其它所有字符集/已知語言的所有字符.

unicode與iso 10646

史上存在兩個嘗試創立單一字符集的組織:

  1. 國際標準化組織ISO——開發了ISO/IEC 10646項目
  2. 統一碼聯盟Unicode Consortium——開發了統一碼項目

1991年前後,兩個項目的參與者都認識到,世界不需要兩個不兼容的字符集。於是,它們開始合併雙方的工作成果,併爲創立一個單一編碼表而協同工作.

到現在兩個項目仍都存在,兩者使用同一字符集,但二者本質上是不同的標準——unicode標準更爲豐富,它額外定義了許多與字符相關的語義符號學,並且部分樣例字形與iso 10646有顯著區別。

unicode的編碼和實現

一般,unicode編碼系統分爲編碼方式(CCS)和實現方式(CEF/CES …).

 

unicode編碼方式(CCS)

統一碼(unicode)的編碼方式使用的是通用字符集UCS. unicode字符的平面映射本質上就是CCS碼位映射,即對字符的編號(ISO/IEC 10646-1所定義)
(CCS)
這個碼位就叫unicode編碼.

  1. 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優缺點

優點

  1. 保證搜索時一個字符的字符串不會出現在另一個字符的串裏面.
  2. 兼容ASCII
  3. 抗干擾和穩定性好:一段兩字節隨機串行碰巧爲合法的UTF-8而非ASCII的機率爲32分1。對於三字節串行的機率爲256分1,對更長的串行的機率就更低了

缺點

  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年推出.

特點

  1. 收錄6763個漢字

編碼結構

先對漢字進行分區(得到的編碼叫區位碼).

  1. 01-09區爲特殊符號。
  2. 16-55區爲一級漢字,按拼音排序。
  3. 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.

 

GBK的編碼範圍
範圍 第1字節 第2字節 編碼數 字數
水準 GBK/1 A1A9 A1FE 846 717
水準 GBK/2 B0F7 A1FE 6,768 6,763
水準 GBK/3 81A0 40FE(7F除外) 6,080 6,080
水準 GBK/4 AAFE 40A0(7F除外) 8,160 8,160
水準 GBK/5 A8A9 40A0(7F除外) 192 166
用戶定義 AAAF A1FE 564  
用戶定義 F8FE A1FE 658  
用戶定義 A1A7 40A0(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完全兼容

編碼結構

  1. 單字節,其值從0到0x7F。
  2. 雙字節,第一個字節的值從0×81到0xFE,第二個字節的值從0×40到0xFE(不包括0x7F)。
  3. 四字節,第一/三字節的值從0×81到0xFE,第二/四字節的值從0×30到0×39.

正則匹配

'#[\x00-\x7f]|[\x81-\xfe][\x40-0xfe]|([\x81-0xfe][\x30-\x39]){2}#'

參考

  1. 維基UCS
  2. 維基字符平面映射
  3. utf_bom
  4. 維基unicode
  5. 維基現代編碼模型
  6. 維基UTF-16
  7. 維基UTF-8
  8. 維基GB2312
  9. 維基GBK
  10. 維基GB18030
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章