unicode和UTF-8的區別

Unicode

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

起源

由於計算機只能處理數字,若是要處理文本,就必須先把文本轉換爲數字才能處理。最先的計算機在設計時採用8個比特(bit)做爲一個字節(byte),因此,一個字節能表示的最大的整數就是255(二進制11111111=十進制255),0 - 255被用來表示大小寫英文字母、數字和一些符號,這個編碼表被稱爲ASCII編碼,好比大寫字母A的編碼是65,小寫字母z的編碼是122。字體

若是要表示中文,顯然一個字節是不夠的,至少須要兩個字節,並且還不能和ASCII編碼衝突,因此,中國製定了GB2312編碼,用來把中文編進去。編碼

相似的,日文和韓文等其餘語言也有這個問題。爲了統一全部文字的編碼,Unicode應運而生。Unicode把全部語言都統一到一套編碼裏,這樣就不會再有亂碼問題了。設計

Unicode一般用兩個字節表示一個字符,原有的英文編碼從單字節變成雙字節,只須要把高字節所有填爲0就能夠。code

由於Python的誕生比Unicode標準發佈的時間還要早,因此最先的Python只支持ASCII編碼,普通的字符串'ABC'在Python內部都是ASCII編碼的。cdn

Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,例如ISO 8859所定義的字符雖然在不一樣的國家中普遍地使用,但是在不一樣國家間卻常常出現不兼容的狀況。不少傳統的編碼方式都有一個共同的問題,即允許電腦處理雙語環境(一般使用拉丁字母以及其本地語言),但卻沒法同時支持多語言環境(指可同時處理多種語言混合的狀況)。blog

Unicode 編碼包含了不一樣寫法的字,如「ɑ/a」、「戶/戶/戸」。然而在漢字方面引發了一字多形的認定爭議。內存

在文字處理方面,統一碼爲每個字符而非字形定義惟一的代碼(即一個整數)。換句話說,統一碼以一種抽象的方式(即數字)來處理字符,並將視覺上的演繹工做(例如字體大小、外觀形狀、字體形態、文體等)留給其餘軟件來處理,例如網頁瀏覽器或是文字處理器。unicode

,世界上存在着多種編碼方式,同一個二進制數字能夠被解釋成不一樣的符號。所以,要想打開一個文本文件,就必須知道它的編碼方式,不然用錯誤的編碼方式解讀,就會出現亂碼。爲何電子郵件經常出現亂碼?就是由於發信人和收信人使用的編碼方式不同。字符串

能夠想象,若是有一種編碼,將世界上全部的符號都歸入其中。每個符號都給予一個獨一無二的編碼,那麼亂碼問題就會消失。這就是 Unicode,就像它的名字都表示的,這是一種全部符號的編碼。

Unicode 固然是一個很大的集合,如今的規模能夠容納100多萬個符號。每一個符號的編碼都不同,好比,U+0639表示阿拉伯字母Ain,U+0041表示英語的大寫字母A,U+4E25表示漢字嚴。具體的符號對應表,能夠查詢unicode.org,或者專門的漢字對應表。

做用

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

層次

Unicode 編碼系統,可分爲編碼方式和實現方式兩個層次。

2.非ASCII編碼

英語用128個符號編碼就夠了,可是用來表示其餘語言,128個符號是不夠的。好比,在法語中,字母上方有注音符號,它就沒法用 ASCII 碼錶示。因而,一些歐洲國家就決定,利用字節中閒置的最高位編入新的符號。好比,法語中的é的編碼爲130(二進制10000010)。這樣一來,這些歐洲國家使用的編碼體系,能夠表示最多256個符號。

可是,這裏又出現了新的問題。不一樣的國家有不一樣的字母,所以,哪怕它們都使用256個符號的編碼方式,表明的字母卻不同。好比,130在法語編碼中表明瞭é,在希伯來語編碼中卻表明了字母Gimel (ג),在俄語編碼中又會表明另外一個符號。可是無論怎樣,全部這些編碼方式中,0--127表示的符號是同樣的,不同的只是128--255的這一段。

至於亞洲國家的文字,使用的符號就更多了,漢字就多達10萬左右。一個字節只能表示256種符號,確定是不夠的,就必須使用多個字節表達一個符號。好比,簡體中文常見的編碼方式是 GB2312,使用兩個字節表示一個漢字,因此理論上最多能夠表示 256 x 256 = 65536 個符號

中文編碼的問題須要專文討論,這篇筆記不涉及。這裏只指出,雖然都是用多個字節表示一個符號,可是GB類的漢字編碼與後文的 Unicode 和 UTF-8 是毫無關係的。

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 的編碼規則很簡單,只有二條:

對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的 Unicode 碼。所以對於英語字母,UTF-8 編碼和 ASCII 碼是相同的。

對於n字節的符號(n > 1),第一個字節的前n位都設爲1,第n + 1位設爲0,後面字節的前兩位一概設爲10。剩下的沒有說起的二進制位,所有爲這個符號的 Unicode 碼。

下表總結了編碼規則,字母x表示可用編碼的位。

跟據上表,解讀 UTF-8 編碼很是簡單。若是一個字節的第一位是0,則這個字節單獨就是一個字符;若是第一位是1,則連續有多少個1,就表示當前字符佔用多少個字節。

下面,仍是以漢字嚴爲例,演示如何實現 UTF-8 編碼。

嚴的 Unicode 是4E25(100111000100101),根據上表,能夠發現4E25處在第三行的範圍內(0000 0800 - 0000 FFFF),所以嚴的 UTF-8 編碼須要三個字節,即格式是1110xxxx 10xxxxxx 10xxxxxx。而後,從嚴的最後一個二進制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就獲得了,嚴的 UTF-8 編碼是11100100 10111000 10100101,轉換成十六進制就是E4B8A5

補充

如今,捋一捋ASCII編碼和Unicode編碼的區別:ASCII編碼是1個字節,而Unicode編碼一般是2個字節。

字母A用ASCII編碼是十進制的65,二進制的01000001;

字符0用ASCII編碼是十進制的48,二進制的00110000,注意字符'0'和整數0是不一樣的;

漢字中已經超出了ASCII編碼的範圍,用Unicode編碼是十進制的20013,二進制的01001110 00101101。

你能夠猜想,若是把ASCII編碼的A用Unicode編碼,只須要在前面補0就能夠,所以,A的Unicode編碼是00000000 01000001。

新的問題又出現了:若是統一成Unicode編碼,亂碼問題今後消失了。可是,若是你寫的文本基本上所有是英文的話,用Unicode編碼比ASCII編碼須要多一倍的存儲空間,在存儲和傳輸上就十分不划算。

因此,本着節約的精神,又出現了把Unicode編碼轉化爲「可變長編碼」的UTF-8編碼。UTF-8編碼把一個Unicode字符根據不一樣的數字大小編碼成1-6個字節,經常使用的英文字母被編碼成1個字節,漢字一般是3個字節,只有很生僻的字符纔會被編碼成4-6個字節。若是你要傳輸的文本包含大量英文字符,用UTF-8編碼就能節省空間:

從上面的表格還能夠發現,UTF-8編碼有一個額外的好處,就是ASCII編碼實際上能夠被當作是UTF-8編碼的一部分,因此,大量只支持ASCII編碼的歷史遺留軟件能夠在UTF-8編碼下繼續工做

在計算機內存中,統一使用Unicode編碼,當須要保存到硬盤或者須要傳輸的時候,就轉換爲UTF-8編碼。

用記事本編輯的時候,從文件讀取的UTF-8字符被轉換爲Unicode字符到內存裏,編輯完成後,保存的時候再把Unicode轉換爲UTF-8保存到文件:

相關文章
相關標籤/搜索