編碼


參考文章:

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

https://mp.weixin.qq.com/s/QjU9lSekpbaF7fugZbyzkg


字節

字節(英語:Byte),通常用作計算機信息計量單位,不分數據類型。 一個字節代表八個比特(英語:Bit)。這個是最基本的概念了,計算機只能識別1和0組成的二進制位。一個數就是1位(bit),為了方便計算,我們規定8位就是一個字節。

例如 :00001111 這個8位二進制數就占了一個字節的存儲容量。

字符

字符和字節不太一樣,任何一個文字或符號都是一個字符,但所占字節不一定,不同的編碼導致一個字符所占的內存不同。字符是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。 也就是說,一個數字是一個字符,一個文字是一個字符,一個標點符號也是一個字符。如:1 是 字符,“漢” 是字符,“!”感嘆號是字符。

字符集

charset 是 character set 的簡寫,即字符集。字符的集合就叫字符集。ASCII字符集就是一種字符集。

編碼

編碼是一個非常寬泛的概念!雖然我們一直用編碼特指字符集編碼,但這只是一種狹義的理解,廣義的理解則有很多:

  • 文字是對聲音的編碼
  • 照相機,攝像機把光信號編碼成圖像及視頻
  • 我們還經常能看到條形碼二維碼,這些都是編碼

著名的摩爾斯電碼其實也是一種編碼:

在圖片中,M的編碼就是“━ ━”,其它類似。

字符編碼 是 編碼的一種情況,不過我們學計算機的說到編碼就是字符編碼。

字符編碼

encoding 是 charset encoding 的簡寫,即字符集編碼,簡稱編碼。定義字符集中的字符如何編碼為特定的二進制數,以便在計算機中存儲(就是將字符在字符集中的對應位置化為二進制)。

字符集和字符編碼一般一 一對應,Unicode字符集例外,因為Unicode字符集有三種編碼方式(utf-8,utf-16,utf-32)

字符編碼 和 字符集的區別

1、字符集表示一定范圍的字符,如A、B定義為字符集1,A、B、C、D定義為字符集2,編碼則是設置字符集中的字符在計算機中的存儲方式,如字符1采用八進制編碼,字符集2采用十六進制編碼。

2、一個字符集可以有多中編碼方式,如Unicode有utf-8,utf-16,utf-32三種編碼方式。

不同的編碼方式都是為了能實現准確表示字符同時存儲空間小且使用簡單。

 

Unicode由來

ASCII 碼

上個世紀60年代,美國制定了一套字符編碼,對英語字符與二進制位之間的關系,做了統一規定。這被稱為 ASCII 碼,一直沿用至今。

ASCII 碼一共規定了128個字符的編碼,比如空格SPACE是32(二進制00100000),大寫的字母A是65(二進制01000001)。這128個符號(包括32個不能打印出來的控制符號),只占用了一個字節的后面7位,最前面的一位統一規定為0

 

中文編碼

ASCII編碼能滿足英文的需求,但是不同的國家都有自己的語言與符號,ASCII肯定是不夠用的,於是不同國家都制定了自己國家語言的編碼,中文編碼演化為:

GB2312(80年代提出,我國簡體中文編碼,包含7445個字符)

-->GBK(90年代提出,包含簡體中文和繁體中文)

-->GB18030(00年代提出,包含簡體中文、繁體中文和少數民族文及特殊符號,字符由1個或2個或4個字節組成)

 

世界編碼各不相同,於是就需要統一世界編碼,於是有了Unicode編碼,Unicode將全世界編碼都進行了統一編碼,世界上所有的字符都分配了一個碼值,類似每個人的身份證號,比如,U+0639表示阿拉伯字母Ain,U+0041表示英語的大寫字母A,U+4E25表示漢字嚴

可以查詢unicode.org,或者專門的漢字對應表

 

Unicode 的問題

需要注意的是,Unicode 只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。

比如,漢字嚴的 Unicode 是十六進制數4E25,轉換成二進制數足足有15位(100111000100101),也就是說,這個符號的表示至少需要2個字節。表示其他更大的符號,可能需要3個字節或者4個字節,甚至更多。

 

這里就有兩個嚴重的問題:

1、如何才能區別 Unicode 和 ASCII ?計算機怎么知道三個字節表示一個符號,而不是分別表示三個符號呢?

2、我們已經知道,英文字母只用一個字節表示就夠了,如果 Unicode 統一規定,每個符號用三個或四個字節表示,那么每個英文字母前都必然有二到三個字節是0,這對於存儲來說是極大的浪費,文本文件的大小會因此大出二三倍,這是無法接受的。

 

它們造成的結果是:

1)出現了 Unicode 的多種存儲方式,也就是說有許多種不同的二進制格式,可以用來表示 Unicode。

2)Unicode 在很長一段時間內無法推廣,直到互聯網的出現。

 

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 編碼非常簡單。如果一個字節的第一位是0,則這個字節單獨就是一個字符;如果第一位是1,則連續有多少個1,就表示當前字符占用多少個字節。

 

由於最高位不同,多字節中不會包含一字節的模式。對於 UTF-8 而言,二字節的模式也不會包含在三字節模式中,也不會在四字節中;三字節模式也不會在四字節模式中,這樣就解決上面所說的搜索匹配難題。

image

可以看到,由於固定位上的 0 和 1 的差別,使得二字節既不會與三字節的前兩字節相同,也不會它的后兩字節相同。

這也每當進行搜索的時候,每個二字節和三字節的編碼沒有重疊,因為最高位不同呀~所以不會出現搜索同一個出現兩個的結果。不過就是有效編碼空間少了.

 

對於0x00-0x7F之間的字符,UTF-8編碼與[ASCII編碼]完全相同。

“漢”字的Unicode編碼是0x6C49。0x6C49在0x0800-0xFFFF之間,使用3字節模板:1110xxxx 10xxxxxx 10xxxxxx。將0x6C49寫成二進制是:0110 1100 0100 1001, 用這個比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

 

UTF-16

Unicode取值范圍目前是 U+0000 ~ U+10FFFF,理論大小為 10FFFF+1=110000(為啥+1,因為從0開始嘛~)。

全部范圍可以均分成 17 個 65536 大小的部分,這里面的每一個部分就是一個平面(Plane)。編號從 0 開始,第一個平面稱為 Plane 0。

 

 

第一個平面即是 BMP(Basic Multilingual Plane 基本多語言平面),也叫 Plane 0,它的碼點范圍是 U+0000 ~ U+FFFF。這也是我們最常用的平面,日常用到的字符絕大多數都落在這個平面內。

 

后續的 16 個平面稱為 SP(Supplementary Planes)。顯然,這些碼點已經是超過 U+FFFF 的了,所以已經超過了 16 位空間的理論上限,對於這些平面內的字符,UTF-16 采用了四字節編碼。

前面的 BMP 縮略圖中有一片空白,這就是所謂的代理區(Surrogate Area)了。

 

 

從 D8~DF。其中前面的紅色部分 D800–DBFF 屬於高代理區(High Surrogate Area),后面的藍色部分 DC00–DFFF 屬於低代理區(Low Surrogate Area),各自的大小均為 4×256=1024。

代理區是 UTF-16 為了編碼增補平面中的字符而保留的,總共有 2048 個位置,均分為高代理區(D800–DBFF)和低代理區(DC00–DFFF)兩部分,各1024,這兩個區組成一個二維的表格,共有1024×1024=210×210=24×216=16×65536,所以它恰好可以表示增補的 16 個平面中的所有字符。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM