文本的编码格式: 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。打開文件后,點擊"文件"菜單中的"另存為"命令,會跳出一個對話框,在最底部有一個"編碼"的下拉條。
里面有四個選項: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位組的串行,以便網絡傳輸和文件存儲.
這里有兩個大背景:
在vim中,:%xxd 可查看相關字符的編碼 :set fileencoding=**可對字符進行編碼轉換
unicode編碼體系
unicode又名統一碼、萬國碼、單一碼、標準萬國碼
意義
因多語言環境的需要而誕生,它對應于ISO 10646通用字符集UCS,包括了其它所有字符集/已知語言的所有字符.
unicode與iso 10646
史上存在兩個嘗試創立單一字符集的組織:
1991年前后,兩個項目的參與者都認識到,世界不需要兩個不兼容的字符集。于是,它們開始合并雙方的工作成果,并為創立一個單一編碼表而協同工作.
到現在兩個項目仍都存在,兩者使用同一字符集,但二者本質上是不同的標準——unicode標準更為豐富,它額外定義了許多與字符相關的語義符號學,并且部分樣例字形與iso 10646有顯著區別。
unicode的編碼和實現
一般,unicode編碼系統分為編碼方式(CCS)和實現方式(CEF/CES …).
?
unicode編碼方式(CCS)
統一碼(unicode)的編碼方式使用的是通用字符集UCS. unicode字符的平面映射本質上就是CCS碼位映射,即對字符的編號(ISO/IEC 10646-1所定義)
(CCS)
這個碼位就叫unicode編碼.
| 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-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
?
| 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優缺點
優點
缺點
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 | |||||||||||||||||||||
| 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 | ||||||||||||||||||||
| 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年推出.
特點
編碼結構
先對漢字進行分區(得到的編碼叫區位碼).
編碼:
對于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 | 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 | ? |
按拼音排序
基于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完全兼容
編碼結構
正則匹配
'#[\x00-\x7f]|[\x81-\xfe][\x40-0xfe]|([\x81-0xfe][\x30-\x39]){2}#'參考
總結
以上是生活随笔為你收集整理的文本的编码格式: ANSI、ASCII、UTF8、UNICODE、GB2312、UCS-2、UTF16的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows常用的网络命令
- 下一篇: QPS、TPS、并发用户数、吞吐量的关系