1. 程式人生 > >編碼格式簡介:ASCII碼、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM頭

編碼格式簡介:ASCII碼、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM頭

family 用兩個 圖片 and 正是 全球化 asc 即使 little

編碼格式簡介:ASCII碼、ANSIGBKGB2312GB18030UnicodeUTF-8BOM

二進制:

只有0和1。

十進制、十六進制、八進制:

計算機其實挺笨的,它只認識0101這樣的字符串(二進制),當然了我們看這樣的01串時肯定會比較頭暈的。

所以很多時候為了描述簡單都用十進制,十六進制,八進制表示。實際上都是等價的,沒啥太多不一樣。

位(bit)

計算機中存儲一個0,或者一個1的位置空間,叫做位。

字節(byte)

計算機中,我們把連續的8個位空間,叫做一個字節。

ASCII碼:

128一版本ASCII碼(7bits)。0-128-255二版本ASCII碼(8bits。首位0,仍為一版本;首位1,為補充字符)

是American Standard Code for Information Interchange的縮寫,美國信息交換標準代碼。

那麽ASCII碼到底是什麽呢?

我們知道其他啥文字圖片之類的其他東東計算機不認識。那為了在計算機上表示這些信息就必須轉換成一些數字。

你肯定不能想怎麽轉換就怎麽轉,必須得有定些規則。

於是剛開始的時候就有ASCII字符集,它使用7 bits來表示一個字符,總共表示128個字符。

我們一般都是用字節(byte,即8個01串)來作為基本單位。

那麽怎麽當用一個字節來表示字符時第一個bit總是0,剩下的七個字節就來表示實際內容。

後來IBM公司在此基礎上進行了擴展,用8bit來表示一個字符,總共可以表示256個字符。也就是當第一個bit是0時仍表示之前那些常用的字符。當為1時就表示其他補充的字符。

ASCII碼是單字節的字符編碼方案,獲得了國際標準化組織的認可,適用於所有拉丁文字字母。

ANSI

ANSI是一種字符代碼,為使計算機支持更多語言,通常使用 0x80-0xFF(十進制為128-255) 範圍的 2 個字節來表示 1 個字符。1.6萬個字符空間。

不同的國家和地區制定了不同的標準,由此產生了各自的編碼標準。

中國使用 2 個字節來代表一個字符的各種漢字,延伸編碼方式的 ANSI 編碼有GB2312 GBK GB18030。

不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。

在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表JIS 編碼。

GB系列

是國家標準代號,就是簡體標準字庫,包括GB2312、GBK、GB18030、Big5(繁體,臺灣和香港使用)。

GB2312

中國人民通過對 ASCII 編碼的中文擴充改造,產生了 GB2312 編碼,可以表示6000多個常用漢字。

GBK

漢字實在是太多了,包括繁體和各種字符,於是產生了 GBK 編碼,它包括了 GB2312 中的編碼,同時擴充了很多。

GB18030

中國是個多民族國家,各個民族幾乎都有自己獨立的語言系統,為了表示那些字符,繼續把 GBK 編碼擴充為 GB18030 編碼。

Big5

又稱為大五碼或者五大碼,是通行於臺灣、香港地區的一個繁體字編碼方案。地區標準號為:CNS11643,這就是人們講的BIG-5碼。

UCS(統一字符集。宏觀)、Unicode、UTF-x微觀

由於不同地區,使用了不同的ANSI字符代碼。終於,有個叫ISO的組織看不下去了。他們一起創造了一種編碼UNICODE,這種編碼非常大,大到可以容納世界上任何一個字符。

ISO取的名字叫UCS(Universal Character Set),UCS對應的編碼格式就叫Unicode。

unicode和ansi都是字符代碼的一種表示形式。unicode是國際標準,ANSI(也就是對美國的ASCII碼的擴展,多字節)是各國標準。例如中國的ANSI代表GB系列,日本的ANSI代表JIS系列。美國直接用ASCII碼(單字節)。

總結起來為啥需要Unicode,就是為了適應全球化的發展,便於不同語言之間的兼容交互,而ASCII不再能勝任此任務了。

unicode的第一個版本

Unicode是用0至65535(2^16)之間的數字來表示所有字符。

是用兩個字節(16bit)來表示所有字符。實際上這麽說容易讓人產生歧義,我們總覺得兩個字節就代表保存在計算機中時是兩個字節。於是任何字符如果用unicode表示的話保存下來都占兩個字節。其實這種說法是錯誤的。

其實Unicode涉及到兩個步驟:

首先是定義一個規範,給所有的字符指定一個唯一對應的數字,65536是2的16次方,這完全是數學問題,可以跟計算機沒半毛錢關系。

第二步才是怎麽把字符對應的數字保存在計算機中,這才涉及到實際在計算機中占多少字節空間。怎麽把0至65535這些數字轉化成01串保存到計算機中。其中0至127這128個數字表示的字符仍然跟ASCII完全一樣。這肯定就有不同的保存方式了。於是出現了UTF(unicode transformation format),有UTF-16,UTF-8。

中文多,優先用UTF-16。(在中國,優先用gbk)

英文多,優先用UTF-8。

小結:中文多,用gbk;英文多,用utf-8。

UTF-16:固定兩個字節

UTF-16比較好理解,就是任何字符對應的數字都用兩個字節來保存。我們通常對Unicode的誤解就是把Unicode與UTF-16等同了。但是很顯然如果都是英文字母這做有點浪費。明明用一個字節能表示一個字符為啥整兩個啊。

UTF-8:可變字節。一個兩個三個都可以。

於是又有個UTF-8,這裏的8非常容易誤導人,8不是指一個字節,難道一個字節表示一個字符?實際上不是。當用UTF-8時表示一個字符是可變的,有可能是用一個字節表示一個字符,也可能是兩個,三個。當然最多不能超過3個字節了。反正是根據字符對應的數字大小來確定。

於是UTF-8和UTF-16的優劣很容易就看出來了。如果全部英文或英文與其他文字混合,但英文占絕大部分,用UTF-8就比UTF-16節省了很多空間。而如果全部是中文這樣類似的字符或者混合字符中中文占絕大多數。UTF-16就占優勢了,可以節省很多空間。另外還有個容錯問題,等會再講。

BOM頭

看的有點暈了吧,舉個例子。

假如中文字"漢"對應的unicode是6C49(這是十六進制,換成十進制27721)。你可能會問當用程序打開一個文件時我們怎麽知道那是用的UTF-8還是UTF-16啊。自然會有點啥標誌,在文件的開頭幾個字節就是標誌,叫做BOM頭。

EF BB BF 表示UTF-8

FE FF 表示UTF-16

用UTF-16表示"漢"

假如用UTF-16表示的話就是01101100 01001001(共16 bit,兩個字節,換成十進制27721)。程序解析的時候知道是UTF-16就把兩個字節當成一個單元來解析。這個很簡單。

用UTF-8表示"漢"

用UTF-8就有復雜點。因為此時程序是把一個字節一個字節的來讀取,然後再根據字節中開頭的bit標誌來識別是該把一個還是兩個或三個字節做為一個單元來處理。

0xxxxxxx,如果是這樣的01串,也就是以0開頭後面是啥就不用管了XX代表任意bit。就表示把一個字節做為一個單元。就跟ASCII完全一樣。

110xxxxx 10xxxxxx。如果是這樣的格式,則把兩個字節當一個單元。

1110xxxx 10xxxxxx 10xxxxxx 如果是這種格式則是三個字節當一個單元。

這是約定的規則。你用UTF-8來表示時必須遵守這樣的規則。我們知道UTF-16不需要用啥字符來做標誌。所以兩字節也就是2的16次能表示65536個字符.

而UTF-8由於裏面有額外的標誌信息。所有一個字節只能表示2的7次方128個字符,兩個字節只能表示2的11次方2048個字符。而三個字節能表示2的16次方,65536個字符。

由於"漢"的編碼27721大於2048了所有兩個字節還不夠,只能用三個字節來表示。

所有要用1110xxxx 10xxxxxx 10xxxxxx這種格式,把27721對應的二進制從左到右填充XXX符號(實際上不一定從左到右,也可以從右到左,這是涉及到另外一個問題。等會說。)

剛說到填充方式可以不一樣,於是就出現了Big-Endian,Little-Endian的術語。Big-Endian就是從左到右(大尾),Little-Endian是從右到左(小尾)。

由上面我們可以看出UTF-8需要判斷每個字節中的開頭標誌信息,所以如果一當某個字節在傳送過程中出錯了,就會導致後面的字節也會解析出錯。而UTF-16不會判斷開頭標誌,即使錯也只會錯一個字符,所以容錯能力強。

Unicode第二個版本

增加了UTF-32,局部重構了Unicode版本1的原樣UTF-8、UTF-16。

前面說的都是unicode的第一個版本,但65536顯然不算太多的數字,用它來表示常用的字符是沒一點問題,足夠了。

但如果加上很多特殊的就也不夠了。於是從1996年開始又來了第二個版本,用四個字節表示所有字符。這樣就出現了UTF-8,UTF16,UTF-32。

原理和之前肯定是完全一樣的,UTF-32就是把所有的字符都用32bit也就是4個字節來表示。

然後UTF-8,UTF-16就視情況而定了。

UTF-8可以選擇1至8個字節中的任一個來表示,而UTF-16只能是選兩字節或四字節。

由於unicode版本2的原理完全是一樣的,就不多說了。

前面說了要知道具體是哪種編碼方式,需要判斷文本開頭的標誌,下面是所有編碼對應的開頭標誌:

EF BB BF    UTF-8

FE FF     UTF-16/UCS-2, little endian

FF FE     UTF-16/UCS-2, big endian

FF FE 00 00  UTF-32/UCS-4, little endian

00 00 FE FF  UTF-32/UCS-4, big endian

其中的UCS就是前面說的ISO制定的標準,和Unicode是完全一樣的,只不過名字不一樣。

ucs-2對應UTF-16;(固定兩個字節)記:宏觀說字節,微觀說位。

ucs-4對應UTF-32;(固定四個字節)

UTF-8是沒有對應的UCS

編碼格式簡介:ASCII碼、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM頭