1、什麼是編碼html
編碼是指信息從一種形式或格式轉換爲另外一種形式或格式的過程。python
在計算機中,編碼,簡而言之,就是將人可以讀懂的信息(一般稱爲明文)轉換爲計算機可以讀懂的信息。衆所周知,計算機可以讀懂的是高低電平,也就是二進制位(0,1組合)。python3.x
而解碼,就是指將計算機的可以讀懂的信息轉換爲人可以讀懂的信息。網絡
2、 編碼的發展淵源編輯器
以前的博客中已經提過,因爲計算機最先在美國發明和使用,因此一開始人們使用的是ASCII編碼。ASCII編碼佔用1個字節,8個二進制位,最多可以表示2**8=256個字符。函數
隨着計算機的發展,ASCII碼已經不能知足世界人民的需求。由於世界各國語言繁多,字符遠遠超過256個。因此各個國家都在ASCII基礎上搞本身國家的編碼。優化
例如中國,爲了處理漢字,設計了GB2312編碼,一共收錄了7445個字符,包括6763個漢字和682個其它符號。1995年的漢字擴展規範GBK1.0收錄了21886個符號。2000年的 GB18030是取代GBK1.0的正式國家標準。該標準收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。編碼
可是,在編碼上,各國」各自爲政「,很難互相交流。因而出現了Unicode編碼。Unicode是國際組織制定的能夠容納世界上全部文字和符號的字符編碼方案。spa
Unicode規定字符最少使用2個字節表示,因此最少可以表示2**16=65536個字符。這樣看來,問題彷佛解決了,各國人民都可以將本身的文字和符號加入Unicode,今後就能夠輕鬆交流了。設計
然而,在當時,計算機的內存容量但是寸土寸金的狀況下,美國等北美洲國家是不接受這個編碼的。由於這憑空增長了他們文件的體積,進而影響了內存使用率,影響工做效率。這就尷尬了。
顯然國際標準在美國這邊不受待見,因此應運而生產生了utf-8編碼。
UTF-8,是對Unicode編碼的壓縮和優化,它再也不要求最少使用2個字節,而是將全部的字符和符號進行分類:ASCII碼中的內容用1個字節保存、歐洲的字符用2個字節保存,東亞的字符用3個字節保存。
這樣,你們各取所需,皆大歡喜。
3、utf-8是如何節省存儲空間和流量的
當計算機在工做時,內存中的數據一直是以Unicode的編碼方式表示的,當數據要保存到磁盤或者網絡傳輸時,纔會使用utf-8編碼進行操做。
在計算機中,」I'm 傑克"的unicode字符集是這樣的編碼表:
I 0x49 ' 0x27 m 0x6d 0x20 傑 0x6770 克 0x514b
每一個字符對應一個十六進制數(方便人們閱讀,0x表明十六進制數),可是計算機只能讀懂二進制數,因此,實際在計算機內表示以下:
I 0b1001001 ' 0b100111 m 0b1101101 0b100000 傑 0b110011101110000 克 0b101000101001011
因爲Unicode規定,每一個字符最少佔用2個字節,因此,以上字符串在內存中的實際佔位以下:
I 00000000 01001001 ' 00000000 00100111 m 00000000 01101101 00000000 00100000 傑 01100111 01110000 克 01010001 01001011
這串字符總共佔用了12個字節,可是對比中英文的二進制碼,能夠發現,英文的前9位都是0,很是的浪費空間和流量。
看看utf-8是怎麼解決的:
I 01001001 ' 00100111 m 01101101 00100000 傑 11100110 10011101 10110000 克 11100101 10000101 10001011
utf-8用了10個字節,對比Unicode,少了2個字節。可是,咱們的程序中不多用到中文,若是咱們程序中90%的內容都是英文,那麼能夠節省45%的存儲空間或者流量。
因此,在存儲和傳輸時,大部分時候遵循utf-8編碼
4、Python2.x與Python3.x中的編解碼
1. 在Python2.x中,有兩種字符串類型:str和unicode類型。str存bytes數據,unicode類型存unicode數據
由上圖能夠看出,str類型存儲的是十六進制字節數據;unicode類型存儲的是unicode數據。utf-8編碼的中文佔3個字節,unicode編碼的中文佔2個字節。
字節數據經常使用來存儲和傳輸,unicode數據用來顯示明文,那如何轉換兩種數據類型呢:
不管是utf-8仍是gbk都只是一種編碼規則,一種把unicode數據編碼成字節數據的規則,因此utf-8編碼的字節必定要用utf-8的規則解碼,不然就會出現亂碼或者報錯的狀況。
python2.x編碼的特點:
爲何英文拼接成功了,而中文拼接就報錯了?
這是由於在python2.x中,python解釋器悄悄掩蓋掉了 byte 到 unicode 的轉換,只要數據所有是 ASCII 的話,全部的轉換都是正確的,一旦一個非 ASCII 字符偷偷進入你的程序,那麼默認的解碼將會失效,從而形成 UnicodeDecodeError 的錯誤。python2.x編碼讓程序在處理 ASCII 的時候更加簡單。你付出的代價就是在處理非 ASCII 的時候將會失敗。
2. 在Python3.x中,也只有兩種字符串類型:str和bytes類型。
str類型存unicode數據,bytse類型存bytes數據,與python2.x比只是換了一下名字而已。
還記得以前博文中提到的這句話嗎?ALL IS UNICODE NOW
python3 renamed the unicode type to str ,the old str type has been replaced by bytes.
Python 3最重要的新特性大概要算是對文本和二進制數據做了更爲清晰的區分,再也不會對bytes字節串進行自動解碼。文本老是Unicode,由str類型表示,二進制數據則由bytes類型表示。Python 3不會以任意隱式的方式混用str和bytes,正是這使得二者的區分特別清晰。你不能拼接字符串和字節包,也沒法在字節包裏搜索字符串(反之亦然),也不能將字符串傳入參數爲字節包的函數(反之亦然)。
注意:不管python2,仍是python3,與明文直接對應的就是unicode數據,打印unicode數據就會顯示相應的明文(包括英文和中文)
5、文件從磁盤到內存的編碼
當咱們在編輯文本的時候,字符在內存對應的是unicode編碼的,這是由於unicode覆蓋範圍最廣,幾乎全部字符均可以顯示。可是,當咱們將文本等保存在磁盤時,數據是怎麼變化的?
答案是經過某種編碼方式編碼的bytes字節串。好比utf-8,一種可變長編碼,很好的節省了空間;固然還有歷史產物的gbk編碼等等。因而,在咱們的文本編輯器軟件都有默認的保存文件的編碼方式,好比utf-8,好比gbk。當咱們點擊保存的時候,這些編輯軟件已經"默默地"幫咱們作了編碼工做。
那當咱們再打開這個文件時,軟件又默默地給咱們作了解碼的工做,將數據再解碼成unicode,而後就能夠呈現明文給用戶了!因此,unicode是離用戶更近的數據,bytes是離計算機更近的數據。
其實,python解釋器也相似於一個文本編輯器,它也有本身默認的編碼方式。python2.x默認ASCII碼,python3.x默認的utf-8,能夠經過以下方式查詢:
import sys print(sys.getdefaultencoding())
若是咱們不想使用默認的解釋器編碼,就得須要用戶在文件開頭聲明瞭。還記得咱們常常在python2.x中的聲明嗎?
#coding:utf-8
若是python2解釋器去執行一個utf-8編碼的文件,就會以默認的ASCII去解碼utf-8,一旦程序中有中文,天然就解碼錯誤了,因此咱們在文件開頭位置聲明 #coding:utf-8,其實就是告訴解釋器,你不要以默認的編碼方式去解碼這個文件,而是以utf-8來解碼。而python3的解釋器由於默認utf-8編碼,因此就方便不少了。
參考資料