給妹子講python-S01E07字符編碼歷史觀-從ASCII到Unicode

歡迎關注公衆號:python數據科學家python

【要點搶先看】編程

1.字符編碼與解碼的概念
2.ASCII編碼到Unicode編碼的發展過程
3.容易混淆的字符編碼與字符代碼ruby

【妹子說】上兩集基本上讓咱們熟悉了字符串的常見用法,不過倒也讓我想起一直以來困惑的一些概念:ASCII碼、Unicode、字符編碼什麼的,一直沒搞明白過,今天不妨就來介紹一下這方面的內容吧。app

關於字符編碼的概念太多太雜,當ASCII、GB23十二、Unicode、UTF-八、UTF-1六、編碼、解碼等諸多名詞一股腦堆上來時,確實容易讓人迷糊。編碼

爲了把這些問題講清楚,今天換一種講法,不講編程,只講故事,從歷史維度,在時間軸上梳理計算機在不一樣語言國家不斷髮展的過程,以此來完全搞清楚這些概念。spa

字符編碼與解碼是什麼?設計

計算機本身能理解的「語言」是二進制數,最小的信息標識是二進制位,8個二進制位表示一個字節;而咱們人類所能理解的語言文字則是一套由英文字母、漢語漢字、標點符號字符、阿拉伯數字等等不少的字符構成的字符集。若是要讓計算機來按照人類的意願進行工做,則必須把人類所使用的這些字符集轉換爲計算機所能理解的二級制碼,這個過程就是編碼,他的逆過程稱爲解碼code

ASCII到Unicode的演進過程orm

計算機最開始在美國被髮明使用,須要編碼的字符集並非很大,無外乎英文字母、數字和一些簡單的標點符號,所以採用了一種單字節編碼系統。在這套編碼規則中,人們將所需字符集中的字符一一映射到128個二進制數上,這128個二進制數最高位爲0,利用剩餘低7位組成00000000~01111111(0X00~0X7F)。cdn

0X00到0X1F這32個二進制數來對控制字符或通訊專用字符(如LF換行、DEL刪除、BS退格)進行編碼,0X20到0X7F共96個二進制數用來對阿拉伯數字、英文字母大小寫和下劃線、括號等符號進行編碼。將這套字符集映射到0X00~0X7F二進制碼的過程就稱爲基礎ASCII編碼,經過這個編碼過程,計算機就將人類的語言轉化爲本身的語言存儲起來;反之,從磁盤中讀取二級制數並轉化爲字母數字等字符以供顯示的過程就是解碼了。

隨着計算機被迅速推廣使用,歐洲非英語國家的人們發現這套由美國人設計的字符集不夠用了,好比一些帶重音的字符、希臘字母等都不在這個字符集中,因而擴充了ASCII編碼規則,將本來爲0的最高位改成1,所以擴展出了10000000~11111111(0X80~0XFF)這128個二進制數。這其中,最優秀的擴展方案是ISO 8859-1,一般稱之爲Latin-1。Latin-1利用128~255這128個二進制數,包括了足夠的附加字符集來涵蓋基本的西歐語言,同時在0~127的範圍內兼容ASCII編碼規則。

隨着使用計算機的國家愈來愈多,天然而然須要編碼的字符集就愈來愈龐大,早先的ASCII編碼字符集因爲受到單字節的限制,其容量就遠遠不夠了,比方說面對成千上萬的漢字,其壓力可想而知。所以中國國家標準總局發佈了一套《信息交換用漢字編碼字符集》的國家標準,其標準號就是GB 2312—1980。這個字符集共收入漢字6763個和非漢字圖形字符682個,採用兩個字節對字符集進行編碼,並向下兼容ASCII編碼方式。簡言之,整個字符集分紅94個區,每區有94個位,分別用一個字節對應表示相應的區和位。每一個區位對應一個字符,所以可用所在的區和位來對漢字進行兩字節編碼。再後來生僻字、繁體字及日韓漢字也被歸入字符集,就又有了後來的GBK字符集及相應的編碼規範,GBK編碼規範也是向下兼容GBK2312的。

在中國發展的同時,計算機在全世界各個國家不斷普及,不一樣的國家地區都會開發出本身的一套編碼系統,所以編碼系統五花八門,這時候問題就開始凸顯了,特別是在互聯網通訊的大環境下,裝有不一樣編碼系統的計算機之間通訊就會彼此不知道對方在「說」些什麼,按照A編碼系統的編碼方式將所需字符轉換成二進制碼後,在B編碼系統的計算機上解碼是沒法獲得原始字符的,相反會出現一些出人意料的古怪字符,這就是所謂的亂碼

那麼統一字符編碼的需求就迫切擺在了你們眼前,爲了實現跨語言、跨平臺的文本轉換和處理需求,ISO國際標準化組織提出了Unicode的新標準,這套標準中包含了Unicode字符集和一套編碼規範。Unicode字符集涵蓋了世界上全部的文字和符號字符,Unicode編碼方案爲字符集中的每個字符指定了統一且惟一的二進制編碼,這就能完全解決以前不一樣編碼系統的衝突和亂碼問題。這套編碼方案簡單來講是這樣的:編碼規範中含有17個組(稱爲平面),每個組含有65536個碼位(例如組0就是0X0000~0XFFFF),每個碼位就惟一對應一個字符,大部分的字符都位於字符集平面0的碼位中,少許位於其餘平面。

字符編碼和字符代碼的概念區分

既然提到了Unicode編碼,那麼經常與之相伴的UTF-8,UTF-16編碼方案又是什麼?其實到目前爲止咱們都一直混淆了兩個概念,即字符代碼字符編碼,字符代碼是特定字符在某個字符集中的序號,而字符編碼是在傳輸、存儲過程中用於表示字符的以字節爲單位的二進制序列。ASCII編碼系統中,字符代碼和字符編碼是一致的,好比字符A,在ASCII字符集中的序號,也就是所謂的字符代碼是65,存儲在磁盤中的二進制比特序列是01000001(0X41,十進制也是65),另外的,如在GB2312編碼系統中字符代碼和字符編碼的值也是一致的,因此無形之中咱們就忽略了兩者的差別性。

而在Unicode標準中,咱們目前使用的是UCS-4,即字符集中每個字符的字符代碼都是用4個字節來表示的,其中字符代碼0~127兼容ASCII字符集,通常的通用漢字的字符代碼也都集中在65535以前,使用大於65535的字符代碼,即須要超過兩個字節來表示的字符代碼是比較少的。所以,若是仍然依舊採用字符代碼和字符編碼相一致的編碼方式,那麼英語字母、數字本來僅需一個字節編碼,目前就須要4個字節進行編碼,漢字本來僅需兩個字節進行編碼,目前也須要4個字節進行編碼,這對於存儲或傳輸資源而言是很不划算的。

所以就須要在字符代碼和字符編碼間進行再編碼,這樣就引出了UTF-八、UTF-16等編碼方式。基於上述需求,UTF-8就是針對位於不一樣範圍的字符代碼轉化成不一樣長度的字符編碼,同時這種編碼方式是以字節爲單位,而且徹底兼容ASCII編碼,即0X00-0X7F的字符代碼和字符編碼徹底一致,也是用一個字節來編碼ASCII字符集,而經常使用漢字在Unicode中的字符代碼是4E00-9FA5,在文末的對應關係中咱們看到是用三個字節來進行漢字字符的編碼。UTF-16同理,就是以16位二進制數爲基本單位對Unicode字符集中的字符代碼進行再編碼,原理和UTF-8一致。

所以,咱們能夠看出,在目前全球互聯的大背景下,Unicode字符集和編碼方式解決了跨語言、跨平臺的交流問題,同時UTF-8等編碼方式又有效的節約了存儲空間和傳輸帶寬,於是受到了極大的推廣應用。

【妹子說】故事講的不錯啊,以前對這些概念感受是一團亂麻,這一集講清楚了字符編碼的發展歷史,容易讓人明白爲何某一時刻就出現了某種編碼方式,搞清楚了前因後果,對字符編碼就好理解了。

附表:

Unicode字符代碼與UTF-8編碼的對應關係

0000 0000-0000 007| 0xxxxxxx

0000 0080-0000 07FF |
 110xxxxx 10xxxxxx

0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

0001 0000-0010 FFFF |
 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
複製代碼

公衆號二維碼:python數據科學家: