字符編碼,ASCII、Unicode與UTF-8的理解
首先我們先要明白的兩點是:1、計算機中的信息都是由二進制的0和1儲存的;2、我們再計算機屏幕上看到的各種字符都是計算機系統按照一定的規則將二進制數字轉換而來的。
一、基本概念。
1、字符集(charset):簡單來說就是計算機支持的所有字符的集合。但字符集並不是一成不變的,隨著計算機在全世界的普及,計算機需要支持的字符越來越多。
2、編碼系統(規則):本質上是一套規則,用來規定一個特定的字符對應的是哪一個二進制數字。所以編碼系統是一個映射的集合,每一個映射的兩端分別是一個字符和一個二進制數字。
3、編碼(encoding):編碼就是字符根據編碼系統轉換成二進制數字的行為。
4、解碼(decoding):解碼就是計算機裏的二進制數字根據編碼系統轉換成字符從而顯示在屏幕上的行為。
二、大話ASCII、Unicode與UTF-8。
在計算機剛開始誕生的時候,全世界只有美國人在用,於是美國人為了讓計算機在屏幕上顯示正常人能看懂的字符,於是便打算搞一套規則對應一些字符。
那時候,美國人規定了一個0或1叫比特(bit),它是計算機信息的最小單位;8個比特稱為1個字節(byte)。
1個字節總共能表示28=256個字符。
但美國人想要顯示的字符不多,加起來也不過127個。於是美國人便規定了1個字符用1個字節表示,很容易發現27=128,所以第一個bit永遠都是0。
美國人那是看到這一套方案工作良好,於是便為它命名為ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼)。
這裏要註意的一點是,ASCII是包括了ASCII字符集和ASCII編碼規則的,ASCII字符集是美國計算機系統上能支持的所有字符的集合,而ASCII編碼規則則是ASCII字符集與二進制數字一一對應的映射。
後來,越來越多的國家開始使用計算機了。比如,中國一些在海外留學的學霸海歸後,順便把計算機搬回了中國使用。但出現了一個很尷尬的問題,並不是所有的人都能很輕松地用英文來工作,而且全英文的文件也不利於信息的傳播。於是中國的工程師便自己搞了套編碼規則,他們規定:原來ASCII裏面的127個字符的字符集和字符編碼依然保留,在此基礎上,凡是出現大於128的字節,該字節就和它下一個字節共同表示1個中文字符。
我們簡單算一下根據這個編碼規則能表示出多少字符:128×28=32768,3萬多個可用空間對於中文字符來說是夠用的了。於是中國的相關組織便把這一套方案命名為GBK(GBK即“國標”、“擴展”漢語拼音的第一個字母,英文名稱:Chinese Internal Code Specification,漢字內碼擴展規範)。
這裏還是要註意一下,GBK也是包括了GBK字符集和GBK編碼規則的。
從此以後,聰明的各國人民也按照差不多的思路,開始編寫了屬於自己國家的字符集和編碼規則了。但這樣會產生一個很嚴重的問題,比如說我本來在一個使用GBK的電腦上編輯的文件放到了一個支持日本字符的計算機上,文件裏的內容就無法正常顯示了。因為文件保存的是0和1,編碼按GBK的編碼,解碼卻按照其他編碼規則來,會使得文件裏得內容不能正常顯示。要說為什麽不能正常顯示呀?因為他們電腦裏支持的字符集根本就沒有中文!
特別使互聯網得快速發展,使得這個問題越來越明顯。
於是,國際標準化組織(International Organization for Standardization,ISO)為了讓計算機能夠盡可能地能夠顯示出全世界得字符,他們就到處收集世界各國的字符,編成了一個集大成的字符集,這個字符集就叫Unicode字符集。原本,ISO用4個字節來制定這套字符集的編碼規則,最常用的是用兩個字節表示一個字符(如果要用到非常偏僻的字符,就需要4個字節),但這是又出現了一個很嚴重的問題,就是如果用2個字節來表示一個字符,那麽第一個字符我就必須用15個0和1個1來表示,就像:00000000 00000001,這樣不僅看上去覺得很不爽,而且有1個字節的0在文件儲存或傳輸時非常消耗成本,因此Unicode字符集雖然是很好,但是在文件的儲存和傳輸方面是十分不經濟的。
由此,UTF-8便應運而生。UTF-8是Unicode字符集的一種相比於原來編碼規則更適合文件儲存和傳輸的編碼規則。
UTF-8是一套字節可變得編碼規則,它用1~6個字節來表示一個字符。UTF-8的編碼規則只有兩條:
1、單字節字符,字節的第一位設為0,後面7位都是可用的二進制位。很容易看出,UTF-8前127個編碼與ASCII編碼是一樣的。
2、n字節字符,第一個字節的前n位都是1,第n+1位是0,第一個字節後面的字節的前兩位都是10,剩下沒有提及的都是可用的二進制位。這一條規則也使得UTF-8編碼即使是一種可變字節的編碼,但也能都被計算機正確識別的原因。
下面是UTF-8的編碼規則,字母x表示可用的編碼位。
簡單一句來說明Unicode與UTF-8的區別:Unicode是一個全世界大部分現存字符的字符集,它有多套編碼規則,其中UTF-8是Unicode使用於文件儲存和傳輸方面的編碼規則。
三、工作中的編碼。
前面第二點說了這麽多ASCII、GBK、Unicode和UTF-8的前世今生,那麽最重要的是我們工作中應該如何巧妙地處理文件的編碼呢?
首先我們理清一下現在計算機系統通用的字符編碼工作方式:
在計算機內存中,統一使用Unicode編碼,當需要保存到硬盤或者需要傳輸的時候,就轉換為UTF-8編碼。
用記事本編輯的時候,從文件讀取的UTF-8字符被轉換為Unicode字符到內存裏,編輯完成後,保存的時候再把Unicode轉換為UTF-8保存到文件:
瀏覽網頁的時候,服務器會把動態生成的Unicode內容轉換為UTF-8再傳輸到瀏覽器:
為什麽有時候會出現亂碼的問題?
首先要明白,我們屏幕上顯示的是Unicode字符,而屏幕下面是Unicode編碼規則對應的二進制數字。
我們一般會出現亂碼的情況時,我由一個文件因為都是中文,所以我就在我電腦上用GBK編碼保存了這個文件,於是計算機系統便用Unicode到GBK的一套轉換算法幫我把文件保存了。目前為止一切的情況都是好的。
但我把我這個文件發到我一個朋友的電腦上,由於他平時都是看的英文文件,所以打開文件的軟件默認是用ASCII編碼,這時他的計算機系統拿著二進制文件,一股腦地每1個字節(8bit)翻譯成英文,這當然是會出問題地啦,甚至可能會出現後128位的數字而顯示不出來,但計算機是很死腦筋的,你說了用ASCII的編碼規則翻譯它就只會每1個字節翻譯成一個字符,所以最後顯示出來屏幕的時候,我們就會看到亂碼了。
除此之外,如果我們用了錯誤的編碼保存也會造成信息的丟失或者報錯。還是那個中文文件,如果我保存用的是ASCII編碼,計算機系統就會每一個字節幫我檢查,當出現了大於128的字節時,就可能會刪去該字節。最常見的是我們編程是,當用到了中文字符,如果我們的編程軟件默認用ASCII編碼,這時是會報錯的,因為計算機不能識別文件中的中文。
所以我們應該怎樣避免亂碼的情況?一般來說我們最好的選擇是,如果文件中出現了除英文字符以外的字符,我們都用UTF-8編碼保存,並且在文本中註明文件的編碼方式是用UTF-8,這樣當傳輸給別人的時候別人就會用UTF-8編碼來打開文件的了。同時我們也要知道,如果別人的文件上寫了這個文件用GBK來編碼,我們打開文件也應該用GBK編碼,否則也會出現亂碼。
具體參考:
1、廖雪峰Python - 字符編碼;
2、博客園,吳秦 - 字符集與字符編碼;
3、簡書,拉丁吳 - utf-8與unicode的區別;
4、博客園,gavin_l - unicode,gbk,utf-8的區別
5、百度經驗 - 區分:編碼方式 字符集 Unicode UTF-8
本人才疏學淺,若文中有理解錯誤的點,懇求指正。
--------本篇完!
字符編碼,ASCII、Unicode與UTF-8的理解