天天看點

字元編碼之ASCII、GB2312、GBK、GB18030、UNICODE、UTF-8、UTF-16、UTF-32、ANSI初步了解

在了解字元編碼之前,先做好準備工作:

  • 工具:UltraEdit,windows自帶文本編輯器。
  • 約定:GBK代表GB2312,GBK,GB18030

首先在UltraEdit輸入一串文字分别儲存為不同編碼格式檢視其16進制。

  • 輸入内容:12Aa練習
  • 結果:如 圖1

圖1

編碼格式 GBK ANSI UNICODE
16進制值     31 32 41 61 C1B7 CFB0    31 32 41 61 C1B7 CFB0          31 32 41 61 7EC3  4E60          
編碼格式        UTF-8 UTF-16LE UTF-16BE
16進制值 31 32 41 61 E7BB83 E4B9A0 3100 3200 4100 6100 C37E 604E 0031 0032 0041 0061 7EC3  4E60

注:輸入内容中的6個字元和圖1中每種編碼下空格隔開的16進制一一對應。

從上圖得出如下現象(後面會對這些現象解釋原由):

  1. 對于輸入内容的數字和英文部分在GBK,ANSI,UNICODE,UTF-8中16進制一緻,在UTF-16BE/LE所占用的位元組數不一緻。
  2. GBK,ANSI的16進制一緻。
  3. 對于輸入内容,把UTF-16BE每個字元的高位元組和低位元組對調就等于UTF-16LE。

ASCII:

在解釋圖1現象之前,了解一下最基本的單位元組編碼系統ASCII(點選檢視詳情),然後得出結論:

  1. ASCII是基本單位元組編碼系統,二進制格式0xxxxxxx,範圍為0-127,16進制範圍00-7F
  2. 隻能表示很小範圍的字元(控制字元+數字+英文等),不能表示中文(GB系列的誕生)。
  3. ASCII在GBK,UTF-8,ANSI,UNICODE表現一緻,後者對ASCII做了相容,是其超集(UNICODE有點特殊,後面會講到)。在UTF-16(LE/BE)上占用位元組數不一樣(前者一個位元組,後者兩個位元組)。

GB系列:

在解釋了ASCII和其他幾種編碼的異同點以及作用後。我們發現一個問題:除了ASCII表上的字元之外,其他的都表示不了,包括中文!包括中文!包括中文!于是GB系列(包括GB2312,GBK,GB18030)誕生了,旨在解決中文字元相關的問題(簡單了解就好)。

GB2312參考:GB2312(點選檢視詳情),GB2312區位碼(點選檢視)

通過上述參考内容得出GB2312結論如下:

  1. GB2312最先誕生,解決簡體中文的編碼問題,用兩個位元組表示一個字元(相容ASCII的部分,ASCII部分仍然一個位元組)。
  2. GB2312采用區位碼的方式表示,一共1-87(十進制)個分區,一共1-94(十進制)個碼位。也就是說GB2312一共87個分區,每個分區有94個碼位,一共可以表示:87x94=8178個字元,其中中文字元16-87分區,一共:(87-15)x94=6768個中文字元。
  3. 為了相容ASSCII,其高位元組必須大于127(0x7F),于是規定:高位元組編碼=分區編号+0xA0,低位元組編碼=碼位編号+0xA0,于是得知高位元組編碼範圍:(1+0xA0)~(87+0xA0)-->0xA1~0xF7,同理,低位元組範圍:0xA1-0xFE,合并後:0xA1A1~0xF7FE。、
  4. 0xA0=160,是以不相容ASCII擴充(範圍128~255),對ASCII擴充感興趣的朋友可以自行查找資料。
  5. 同時我們發現GB2312并不完美,很多生僻字和繁體字并沒有與之對應的編碼(GBK的誕生)。

GBK參考:GBK(點選檢視詳情),GBK區位碼(點選檢視)

為了解決上述結論5,誕生了GBK,通過GBK參考得出結論如下:

  1. GBK是對GB2312的擴充,相容GB2312,同時相容BIG5(台灣繁體編碼),支援中日韓新等統一編碼規範(CJK)
  2. 同樣采用了區位碼,分區:0x81~FE,碼位:0x40~FE。不用+0xA0,合并後範圍:0x8140-FEFE。
  3. 由于曆史原因(windows,linux上中文預設編碼都是GBK),導緻GBK是GB系列windows,linux的主流。
  4. GB2312和GBK都不支援少數民族文字,同時都不支援國際化,于是誕生GB18030。

GB18030參考:GB18030(點選檢視詳情),GB18030編碼研究(點選檢視)

為了解決上述結論4,誕生了GB18030,通過GB18030參考得出結論如下:

  1. GB18030是對GBK的擴充,目前主流,新增了少數名族文字,支援單位元組,雙位元組,四位元組。
  2. 實作了UCS4(後面會詳細講到),國際統一标準。

以上就了解完了GB系列的相關知識,細心的朋友會發現兩個問題:

  1. 假設有很多種類似GBK的編碼,那麼我們到底該選擇那種編碼呢?(ANSI的誕生)
  2. GB18030是如何保證相容GBK的情況下同時實作UCS4的呢?(暫時保留)

ANSI:

為了解決上述問題1,我們為每個國家設定不同的預設編碼,那麼這個被設定的編碼同時又叫做ANSI(微軟幹的好事),說以在中國ANSI=GBK。好處是解決了字元編碼選擇問題。但是不能解決本質問題:

不同編碼互相轉換問題。如GB2312和BIG5之間大部分字元是不能互相轉換的(上面的知識點可以證明)。我們可以試想幾種方式來解決。

  1. 通過翻譯的方式來映射(難度太大,現實)。
  2. 字元統一編碼,所有的字元編碼不重複,并被所有人認可。(UNICODE的誕生)。

UNICODE:

UNICODE參考:UNICODE(點選檢視詳情)

全稱:unicode character set 别名UCS(後面提到UCS和UNICODE是一個意義),對照參考可以得出以下結論:

  1. 包含UCS2和UCS4,分别用最大2個和4個位元組來給字元進行邏輯編碼。
  2. UNICODE隻是為字元制定了統一的邏輯編碼(之後統一簡稱UNICODE碼),并沒有定義其在計算機中的存儲編碼。
  3. 對于儲存編碼并不強求相容已經存在的任何一種編碼方式,但是UNICODE碼卻是和ASSCII編碼的數值大小保持了一緻。
  4. UNICODE隻是制定了一套編碼規範,并沒有具體的實作(結論3的延續),需要開發商自行實作(UTF16的誕生)。

UTF-16:

UTF全稱:Unicode Transformation Format

這裡講解的UTF-16,主要是UTF-16BE(大端),UTF-16LE(小端)自行了解。一般我們會在文本首部加上FEFF來表示大端,FFFE來表示小端。這種方式通常稱為BOM(Byte Order Mark)。對UTF-16加上BOM可以保證字元編碼的正确解析,UTF-16中的16表示16位,即2個位元組定長(65536個字元),實作了UCS2。

其實UTF-16的實作方式很簡單,就是把UNICODE碼一一對應過來,高位不足就補0,直到補滿16位,是以才導緻ASCII篇的結論3(但是并不相容ASCII)。同時我們會發現如下問題:

  1. 在網絡通信中大小端問題需要自己解決,能表示的字元範圍有限。(UTF-8的誕生)

UTF-8:

UTF-8,目前應用最廣泛,前景最好的編碼,沒有之一,極力推薦。

特點:變長(位數是8的倍數),靈活,表示範圍廣,對UCS4的實作。

我們把UNICODE碼用二進制表示,其長度記着LEN,UTF-8所占位元組數記着N,存儲編碼規則如下:

  • 當LEN<8,N=1,同時與UNICODE碼保持一緻,(是以相容ASCII)。
  • 當LEN>=8,N=LEN/6+1,依據:最高一個位元組的前n個連續的1表示n個位元組,後面緊跟一個0。剩下n-1個位元組,每個位元組的前兩位都以10表示。如2位元組表示:110xxxxx 10xxxxxx , 3位元組1110xxxx 10xxxxxx 10xxxxxx。 最後推理出  N<8。 同時N越大存儲浪費也越大。

UTF-32:

 沒啥好說的,類似UTF-16,比UTF-8/16表示範圍大。

總結:

字元編碼之ASCII、GB2312、GBK、GB18030、UNICODE、UTF-8、UTF-16、UTF-32、ANSI初步了解

繼續閱讀