編碼方式部分信息整合:Unicode、UCS-2/4、UTF-8/16/32、GB2312、GBK

以下信息統計皆來自百度百科

 

ISO:國際標準化組織(International Organization for Standardization,ISO)簡稱ISO。負責目前絕大部分領域(包括軍工、石油、船舶等壟斷行業)的標準化活動。

------------------

UTF:(Unicode Transformation Format)通用轉換格式 或 Unicode字符集轉換格式。屬於Unicode Standard的常用編碼方式還有UTF-8、UTF-16、UTF-32。UTF-1、UTF-7、UTF-EBCDIC不再是Unicode Standard的部分。

------------------

Unicode:(統一碼、萬國碼、單一碼)是計算機科學領域裏的一項業界標準,包括字符集、編碼方案等。它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。

    由來:初期有ASCII編碼,但漢子至少需要兩個字節,所以中國製定了GB2312編碼。其他國家也有類似編碼。幾乎所有電腦系統都支持基本拉丁字母,並各自支持不同的其他編碼方式。爲了統一,產生了Unicode。

    作用:使計算機實現跨語言、跨平臺的文本轉換及處理。

    映射方式:兩種。一種叫the Unicode Transformation Format (UTF) 編碼。還有一種叫 Universal Character Set (UCS) 編碼。一種編碼映射一定範圍(可能是子集)的Unicode 碼點(code points )成代碼值(code value)的序列。編碼名字後面的數字代表一個代碼值的位數(UTF使用位數,UCS 使用字節數),UTF-8 和UTF-16是最常使用的編碼,其中8、16都是位數(bit),而UCS-2和UCS-4較爲常用,其中2、4都是字節數。

    層次:分爲編碼方 和實現方式

    編碼方式:UTF-8、UTF-16、UTF-32都是將數字轉換到程序數據的編碼方案。

    不直接用Unicode的原因:事實證明,對可以用ASCII表示的字符使用UNICODE並不高效,因爲UNICODE比ASCII佔用大一倍的空間,而對ASCII來說高字節的0對他毫無用處。爲了解決這個問題,就出現了一些中間格式的字符集,他們被稱爲通用轉換格式,即UTF(Unicode Transformation Format)。常見的UTF格式有:UTF-8,UTF-16, 以及 UTF-32。

    Unicode的最大碼位是0x10FFFF。

    環境:在非 Unicode 環境下,由於不同國家和地區採用的字符集不一致,很可能出現無法正常顯示所有字符的情況。微軟公司使用了代碼頁(Codepage)轉換表的技術來過渡性的部分解決這一問題,即通過指定的轉換表將非 Unicode 的字符編碼轉換爲同一字符對應的系統內部使用的 Unicode 編碼。可以在“語言與區域設置”中選擇一個代碼頁作爲非 Unicode 編碼所採用的默認編碼方式,如936爲簡體中文GBK,950爲繁體中文Big5(皆指PC上使用的)。在這種情況下,一些非英語的歐洲語言編寫的軟件和文檔很可能出現亂碼。而將代碼頁設置爲相應語言中文處理又會出現問題,這一情況無法避免。從根本上說,完全採用統一編碼纔是解決之道,但是Windows操作系統由於歷史遺留原因尚無法做到這一點。

        代碼頁技術廣泛爲各種平臺所採用。UTF-7 的代碼頁是65000,UTF-8 的代碼頁是65001。

------------------

UCS:(Universal Character Set)通用字符集,是由ISO制定的ISO 10646(或稱ISO/IEC 10646)標準所定義的字符編碼方式,採用4字節編碼。UCS包括了所有其他字符集。它保證了與其他字符集的雙向兼容,即,如果你將任何文本字符串翻譯到UCS格式,然後再翻譯回原編碼,你不會丟失任何信息。UCS包含了已知語言的所有字符。

    命名:UCS不僅給每個字符分配一個代碼,而且賦予了一個正式的名字。表示一個UCS或Unicode值的十六進制數通常在前面加上“U+”,例如“U+0041”代表字符“A”。

    編碼方式:UCS-2,UCS-4,2和4分別代表字節數。

------------------

BMP:(Basic Multilingual Plane)基本多文種平面或基本多語言面,或稱第零平面(Plane 0)。是Unicode(或者UCS)中的一個編碼區段。詳見 基本多文種平面·百度百科

輔助平面:鑑於 Unicode 原有的16位元空間不足以應用,從 Unicode 3.1 版本開始,設立了16個輔助平面,使 Unicode 的可使用空間由六萬多字增至約一百萬字。原有的 Unicode 空間稱爲基本平面或基本多文種平面 (Basic Multilingual Plane, 簡稱 BMP)。輔助平面字符要用上4字節來儲存。詳見 輔助平面·百度百科

------------------

UCS與Unicode:分屬不同組織,分別是Unicode組織和ISO組織。UCS與 Unicode組織的Unicode編碼完全兼容。

    具體關係:Unicode組織和ISO組織都試圖定義一個超大字符集,目的是要涵蓋所有語言使用的字符以及其他學科使用的一些特殊符號,這個字符集就是通用字符集(UCS,Universal Character Set)。這兩個組織經過協調,雖然在各自發展,但定義的字符位置是完全一致的。ISO相應的標準是ISO 10646。Unicode和ISO 10646都在不斷的發展過程中,所以會有不同的版本號來標明不同的發展階段,每個Unicode版本號都能找到相對應的ISO 10646版本號。

    ISO 10646標準定義了一個31位的字符集。前(低)兩個字節的位置(0x0000-0xFFFD)被稱爲基本多語言面(Basic Multilingual Plane, BMP) ,超出兩個字節的範圍稱作輔助語言面。BMP基本包括了所有語言中絕大多數字符,所以只要支持BMP就可以支持絕大多數場合下的應用。Unicode 3.0對應的字符集在BMP範圍內。

    UCS字符集和Unicode字符集並不適合直接實際應用。UTF-8、UTF-16、UTF-32、UCS-2、UTF-16是Unicode字符集或者UCS字符集實際應用中的具體編碼方式。

------------------

拉丁字母:是目前世界上流傳最廣的字母體系(就是我們常用的26個大小寫英文字母),源自希臘字母。中國漢語拼音方案也已採用拉丁字母。由於形體簡單清楚,便於認讀書寫,流傳很廣,成爲世界最通行的字母。

------------------

編碼方式:

ASCII:(American Standard Code for Information Interchange)美國信息交換標準碼,是一種標準的單字節字符編碼方案,用於基於文本的數據。基於拉丁字母的一套電腦編碼系統,後被ISO定爲國際標準,稱爲ISO 646標準。適用於所有拉丁文字字母;幾乎所有電腦系統都支持基本拉丁字母。

ISO-8859-1:別名Latin-1,單字節編碼,向下兼容ASCII。此字符集支持部分於歐洲使用的語言。因爲ISO-8859-1編碼範圍使用了單字節內的所有空間,在支持ISO-8859-1的系統中傳輸和存儲其他任何編碼的字節流都不會被拋棄。換言之,把其他任何編碼的字節流當作ISO-8859-1編碼看待都沒有問題。這是個很重要的特性,MySQL數據庫默認編碼是Latin1就是利用了這個特性。

GB2312:1980 年制定的中國漢字編碼國家標準。共收錄 7445 個字符,其中漢字 6763 個。兼容標準 ASCII碼,採用擴展 ASCII 碼的編碼空間進行編碼,一個漢字佔用兩個字節,每個字節的最高位爲 1。EUC-CN是GB2312最常用的表示方法。瀏覽器編碼表上的“GB2312”,通常都是指“EUC-CN”表示法。EUC-CN可以理解爲GB2312的別名,和GB2312完全相同。 GB2312是基於區位碼設計的,區位碼和GB2312編碼的關係有點像 Unicode和UTF-8。

GBK:《漢字內碼擴展規範》(GBK) 於1995年制定,兼容GB2312、GB13000-1、BIG5 編碼中的所有漢字,使用雙字節編碼,編碼空間爲 0x8140~0xFEFE,共有 23940 個碼位,其中 GBK1 區和 GBK2 區也是 GB2312 的編碼範圍。收錄了 21003 個漢字。GBK向下與 GB 2312 編碼兼容,向上支持 ISO 10646.1(由其標準定義的編碼方式是UCS)國際標準,是前者向後者過渡過程中的一個承上啓下的產物。我國 1993 年以 GB 13000.1 國家標準的形式予以認可UCS(即 GB 13000.1 等同於 ISO 10646.1)

    存在的問題:低字節是0x40-0x7E的GBK字符有一定特殊性,因爲這些字符佔用了ASCII碼的位置,這樣會給一些系統帶來麻煩。

    有些系統中用0x40-0x7E中的字符(如“|”)做特殊符號,在定位這些符號時又沒有判斷這些符號是不是屬於某個 GBK字符的低字節,這樣就會造成錯誤判斷。在支持GB2312的環境下就不存在這個問題。需要注意的是支持GBK的環境中小於0x80的某個字節未必就 是ASCII符號;另外就是最好選用小於0×40的ASCII符號做一些特殊符號,這樣就可以快速定位,且不用擔心是某個漢字的另一半。Big5編碼中也存在相應問題。

GB18030:國家標準GB18030-2000《信息交換用漢字編碼字符集基本集的補充》是我國繼GB2312-1980和GB13000-1993之後最重要的漢字編碼標準,是我國計算機系統必須遵循的基礎性標準之一。GB18030-2000編碼標準是由信息產業部和國家質量技術監督局在2000年 3月17日聯合發佈的,並且將作爲一項國家標準在2001年的1月正式強制執行。GB18030-2005《信息技術中文編碼字符集》是我國制訂的以漢字爲主幷包含多種我國少數民族文字(如藏、蒙古、傣、彝、朝鮮、維吾爾文等)的超大型中文編碼字符集強制性標準,其中收入漢字70000餘個 。GB18030編碼向下兼容GBK和GB2312,兼容的含義是不僅字符兼容,而且相同字符的編碼也相同。GB18030收錄了所有Unicode3.1中的字符,包括中國少數民族字符,GBK不支持的韓文字符等等,也可以說是世界大多民族的文字符號都被收錄在內。

    GBK和GB2312都是雙字節等寬編碼,如果算上和ASCII兼容所支持的單字節,也可以理解爲是單字節和雙字節混合的變長編碼。GB18030編碼是變長編碼,有單字節、雙字節和四字節三種方式。

BIG5:是雙字節編碼。收錄的漢字只包括繁體漢字,不包括簡體漢字,一些生僻的漢字也沒有收錄。Big5編碼對應的字符集是GBK字符集的子集,也就是說Big5收錄的字符是GBK收錄字符的一部分,但相同字符的編碼不同。Windows系統上使用的代碼頁CP950也可以理解爲是對Big5的擴展,在Big5的基礎上增加了7個漢字和一些符號。儘管有些區別,大多數情況下可以把CP950當作Big5的別名。

UCS-2和UTF-16:UCS-2是兩個字節的等寬編碼,因爲只是使用了兩個字節的編碼空間,所以只能對BMP中的字符做編碼。UTF-16是變長編碼,用兩個字節對BMP內的字符編碼,用4個字節對超出BMP範圍的輔助平面內的字符作編碼。UTF-16是UCS-2的超集,UTF-16編碼的兩字節編碼方式完全和UCS-2相同,也就是說在BMP的框架內UCS-2完全等同與UTF-16。實際情況當中常常把UCS-16當作UCS-2的別名。

    UCS-2和UTF-16在存儲和傳輸時會使用兩種不同的字節序,分別是big endian和little endian,在傳輸過程中爲了說明字節序需要在字節流前加上BOM(Byte order Mark),0xFEFF表示是big endian,0xFFFE表示是little endian。UCS-2BE、UCS-2LE是實際應用中使用的編碼名稱,對應着big endian和little endian,UTF-16BE、UTF-16LE也是如此。因爲默認是BE字節序,所以可以把UCS-2當做是UCS-2BE的別名。在UCS編碼中有一個叫做“ZERO WIDTH NO-BREAK SPACE”的字符,它的編碼是U+FEFF,是個沒有實際意義的字符。UCS規範建議我們在傳輸字節流前,先傳輸字符“ZERO WIDTH NO-BREAK SPACE”,如果傳輸的ZERO WIDTH NO-BREAK SPACE是0xFEFF就說明是big endian,反之就是little endian。

    UCS-2和UTF-16也可以理解爲和ASCII以及ISO-8859-1兼容,在ASCII編碼或者ISO-8859-1編碼的每個字節前加上0x00,就得到相應字符的UCS-2編碼。UCS-2和UTF-16中會使用0x00作爲某個字符編碼的一部分,某些系統會把0x00當作字符串結束的標誌,在處理UCS-2或UTF-16編碼時會出現問題。

UTF-8:英文使用8位(即一個字節),中文使用24位(三個字節)來編碼。

    編碼規則:如果只有一個字節則其最高二進制位爲0;如果是多字節,其第一個字節從最高位開始,連續的二進制位值爲1的個數決定了其編碼的字節數,其餘各字節均以10開頭。UTF-8轉換表表示如下:

Unicode/UCS-4

bit數

UTF-8

byte數

備註

0000 ~

007F

0~7

0XXX XXXX

1

 

0080 ~

07FF

8~11

110X XXXX

10XX XXXX

2

 

0800 ~

FFFF

12~16

1110 XXXX

10XX XXXX

10XX XXXX

3

基本定義範圍:0~FFFF

1 0000 ~

1F FFFF

17~21

1111 0XXX

10XX XXXX

10XX XXXX

10XX XXXX

4

Unicode6.1定義範圍:0~10 FFFF

20 0000 ~

3FF FFFF

22~26

1111 10XX

10XX XXXX

10XX XXXX

10XX XXXX

10XX XXXX

5

說明:此非unicode編碼範圍,屬於UCS-4 編碼

早期的規範UTF-8可以到達6字節序列,可以覆蓋到31位元(通用字符集原來的極限)。儘管如此,2003年11月UTF-8 被 RFC 3629 重新規範,只能使用原來Unicode定義的區域, U+0000到U+10FFFF。根據規範,這些字節值將無法出現在合法 UTF-8序列中

400 0000 ~

7FFF FFFF

27~31

1111 110X

10XX XXXX

10XX XXXX

10XX XXXX

10XX XXXX

10XX XXXX

6

    實際表示ASCII字符的UNICODE字符,將會編碼成1個字節,並且UTF-8表示與ASCII字符表示是一樣的。所有其他的UNICODE字符轉化成UTF-8將需要至少2個字節。每個字節由一個換碼序列開始。第一個字節由唯一的換碼序列,由n位連續的1加一位0組成, 首字節連續的1的個數表示字符編碼所需的字節數。

    Unicode轉換爲UTF-8時,可以將Unicode二進制從低位往高位取出二進制數字,每次取6位,如上述的二進制就可以分別取出爲如下示例所示的格式,前面按格式填補,不足8位用0填補。

    Unicode轉換爲UTF-8需要的字節數可以根據這個規則計算:如果Unicode小於0X80(Ascii字符),則轉換後爲1個字節。否則轉換後的字節數爲Unicode二進制位數+3再除以5。

    UCS-4也是一種UCS字符集的編碼方式,是使用4個字節的等寬編碼,可以用UCS-4來表示BMP之外的輔助面字符。UCS-2中每兩個字節前再加上0x0000就得到了BMP字符的UCS-4編碼。從UCS-4到UTF-8也存在轉換關係,根據這種轉換關係,UTF-8最多可以使用六個字節來編碼UCS-4。根據UTF-8的生成規律和UCS字符集的特性,可以看到UTF-8具有的特性:

    UTF-8完全和ASCII兼容,也就是說ASCII對應的字符在UTF-8中和ASCII編碼完全一致。範圍在0x00-0x7F之內的字符一定是ASCII字符,不可能是其他字符的一部分。GBK和Big5都存在的缺陷在UTF-8中是不存在的。

    大於U+007F的UCS字符,在UTF-8編碼中至少是兩個字節。

    UTF-8中的每個字符編碼的首字節總在0x00-0xFD之間(不考慮UCS-4支持的情況,首字節在0x00-0xEF之間)。根據首字節就可以判斷之後連續幾個字節。

    非首字節的其他字節都在0x80-0xBF之間;0xFE和0xFF在UTF-8中沒有被用到。

    GBK編碼中的漢字字符都在UCS-2中的範圍都在U+0800 - U+FFFF之間,所以每個GBK編碼中的漢字字符的UTF-8編碼都是3個字節。但GBK中包含的其他字符的UTF-8編碼就不一定是3個字節了,如GBK中的俄文字符。

    在UTF-8的編碼的傳輸過程中即使丟掉一個字節,根據編碼規律也很容易定位丟掉的位置,不會影響到其他字符。在其他雙字節編碼中,一旦損失一個字節,就會影響到此字節之後的所有字符。從這點可以看出UTF-8編碼非常適合作爲傳輸編碼。

    編碼字節數:
        UTF-8使用1~4字節爲每個字符編碼:
        ·一個US-ASCIl字符只需1字節編碼(Unicode範圍由U+0000~U+007F)。
        ·帶有變音符號的拉丁文、希臘文、西裏爾字母、亞美尼亞語、希伯來文、阿拉伯文、敘利亞文等字母則需要2字節編碼(Unicode範圍由U+0080~U+07FF)。
        ·其他語言的字符(包括中日韓文字、東南亞文字、中東文字等)包含了大部分常用字,使用3字節編碼。
        ·其他極少使用的語言字符使用4字節編碼。


    優點:
        UTF-8編碼可以通過屏蔽位和移位操作快速讀寫。字符串比較時strcmp()和wcscmp()的返回結果相同,因此使排序變得更加容易。字節FF和FE在UTF-8編碼中永遠不會出現,因此他們可以用來表明UTF-16或UTF-32文本(見BOM) UTF-8 是字節順序無關的。它的字節順序在所有系統中都是一樣的,因此它實際上並不需要BOM。


    缺點
         你無法從UNICODE字符數判斷出UTF-8文本的字節數,因爲UTF-8是一種變長編碼它需要用2個字節編碼那些用擴展ASCII字符集只需1個字節的字符 ISO Latin-1 是UNICODE的子集,但不是UTF-8的子集 8位字符的UTF-8編碼會被email網關過濾,因爲internet信息最初設計爲7位ASCII碼。因此產生了UTF-7編碼。 UTF-8 在它的表示中使用值100xxxxx的機率超過50%, 而現存的實現如ISO 2022, 4873, 6429, 和8859系統,會把它錯認爲是C1 控制碼。因此產生了UTF-7.5編碼。

    UTF-16:UTF-16是Unicode字符編碼五層次模型的第三層,字符編碼表(Character Encoding Form,)的一種實現方式。即把Unicode的字符集的抽象碼位映射爲16位長的整數(即碼元)的序列,用於數據存儲或傳遞。Unicode字符的碼位,需要1個或者2個16位長的碼元來表示,因此這是一個變長表示。UTF-16比起UTF-8,好處在於大部分字符都以固定長度的字節 (2字節) 儲存,但UTF-16卻無法兼容於ASCII編碼。

    編碼過程:見Unicode·百度百科.UTF-16

    大小端:一般來說,以Macintosh製作或儲存的文字使用大尾序格式,以Microsoft或Linux製作或儲存的文字使用小尾序格式。詳見BOM。

    與UCS-2關係:UTF-16可看成是UCS-2的父集。在沒有輔助平面字符(surrogate code points)前,UTF-16與UCS-2所指的是同一的意思。但當引入輔助平面字符後,就稱爲UTF-16了。現在若有軟件聲稱自己支持UCS-2編碼,那其實是暗指它不能支持在UTF-16中超過2bytes的字集。對於小於0x10000的UCS碼,UTF-16編碼就等於UCS碼。

UTF-32:編碼以32位無符號整數爲單位。Unicode的UTF-32編碼就是其對應的32位無符號整數。大多數情況下等同於UCS-4。固定長度編碼。

    大小端:詳見BOM。

    編碼舉例:

Unicode編碼

UTF-16LE 

UTF-16BE 

UTF32-LE 

UTF32-BE

0x006C49

49 6C

6C 49

49 6C 00 00

00 00 6C 49

0x020C30

30 DC 43 D8

D8 43 DC 30

30 0C 02 00

00 02 0C 30

ANSI:(American National Standards Institute),中文:美國國家標準學會。“ANSI編碼”只存在於Windows系統。不同的國家和地區制定了不同的標準,由此產生了 GB2312、GBK、Big5、Shift_JIS 等各自的編碼標準。這些使用 1 至 4 個字節來代表一個字符的各種漢字延伸編碼方式,稱爲 ANSI 編碼。在簡體中文Windows操作系統中,ANSI 編碼代表 GBK 編碼;在日文Windows操作系統中,ANSI 編碼代表 Shift_JIS 編碼。 不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。 當然對於ANSI編碼而言,0x00~0x7F之間的字符,依舊是1個字節代表1個字符。這一點是ANSI編碼與Unicode編碼之間最大也最明顯的區別。詳見ansi編碼·百度百科&ANSI·百度百科

------------------

BOM:(字節順序標記(ByteOrderMark)),字節順序標記,出現在文本文件頭部,Unicode編碼標準中用於標識文件是採用哪種格式的編碼。

    BOM —— Byte Order Mark,中文名譯作“字節順序標記”。在這裏找到一段關於 BOM 的說明:

    在UCS 編碼中有一個叫做 "Zero Width No-Break Space" ,中文譯名作“零寬無間斷間隔”的字符,它的編碼是 FEFF。而 FEFF 在 UCS 中是不存在的字符,所以不應該出現在實際傳輸中。UCS 規範建議我們在傳輸字節流前,先傳輸字符 "Zero Width No-Break Space"。這樣如果接收者收到 FEFF,就表明這個字節流是 Big-Endian 的;如果收到FFFE,就表明這個字節流是 Little- Endian 的。因此字符 "Zero Width No-Break Space" (“零寬無間斷間隔”)又被稱作 BOM。

    UTF-8 不需要 BOM 來表明字節順序,但可以用 BOM 來表明編碼方式。字符 "Zero Width No-Break Space" 的 UTF-8 編碼是 EF BB BF。所以如果接收者收到以 EF BB BF 開頭的字節流,就知道這是 UTF-8編碼了。Windows 就是使用 BOM 來標記文本文件的編碼方式的。

    字符U+FEFF如果出現在字節流的開頭,則用來標識該字節流的字節序,是高位在前還是低位在前。如果它出現在字節流的中間,則表達零寬度非換行空格的意義,用戶看起來就是一個空格。從Unicode3.2開始,U+FEFF只能出現在字節流的開頭,只能用於標識字節序,就如它的名稱——字節序標記——所表示的一樣;除此以外的用法已被捨棄。取而代之的是,使用U+2060來表達零寬度無斷空白。

    類似WINDOWS自帶的記事本等軟件,在保存一個以UTF-8編碼的文件時,會在文件開始的地方插入三個不可見的字符(0xEF 0xBB 0xBF,即BOM)。它是一串隱藏的字符,用於讓記事本等編輯器識別這個文件是否以UTF-8編碼。對於一般的文件,這樣並不會產生什麼麻煩。但對於 PHP來說,BOM是個大麻煩。

    PHP並不會忽略BOM,所以在讀取、包含或者引用這些文件時,會把BOM作爲該文件開頭正文的一部分。根據嵌入式語言的特點,這串字符將被直接執行(顯示)出來。由此造成即使頁面的 top padding 設置爲0,也無法讓整個網頁緊貼瀏覽器頂部,因爲在html一開頭有這3個字符呢!

    不同編碼的字節順序標記的表示:

編碼

表示 (十六進制)

表示 (十進制)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章