1. 程式人生 > >【轉】python基礎-編碼與解碼

【轉】python基礎-編碼與解碼

什麽 浪費 2.x sys 拼接 aced tro lte bytes

【轉自:https://www.cnblogs.com/OldJack/p/6658779.html】

一、什麽是編碼

編碼是指信息從一種形式或格式轉換為另一種形式或格式的過程。

在計算機中,編碼,簡而言之,就是將人能夠讀懂的信息(通常稱為明文)轉換為計算機能夠讀懂的信息。眾所周知,計算機能夠讀懂的是高低電平,也就是二進制位(0,1組合)。

而解碼,就是指將計算機的能夠讀懂的信息轉換為人能夠讀懂的信息。

二、 編碼的發展淵源

之前的博客中已經提過,由於計算機最早在美國發明和使用,所以一開始人們使用的是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是國際組織制定的可以容納世界上所有文字和符號的字符編碼方案。

Unicode規定字符最少使用2個字節表示,所以最少能夠表示2**16=65536個字符。這樣看來,問題似乎解決了,各國人民都能夠將自己的文字和符號加入Unicode,從此就可以輕松交流了。

然而,在當時,計算機的內存容量可是寸土寸金的情況下,美國等北美洲國家是不接受這個編碼的。因為這憑空增加了他們文件的體積,進而影響了內存使用率,影響工作效率。這就尷尬了。

顯然國際標準在美國這邊不受待見,所以應運而生產生了utf-8編碼。

UTF-8,是對Unicode編碼的壓縮和優化,它不再要求最少使用2個字節,而是將所有的字符和符號進行分類:ASCII碼中的內容用1個字節保存、歐洲的字符用2個字節保存,東亞的字符用3個字節保存。

這樣,大家各取所需,皆大歡喜。

三、utf-8是如何節省存儲空間和流量的

當計算機在工作時,內存中的數據一直是以Unicode的編碼方式表示的,當數據要保存到磁盤或者網絡傳輸時,才會使用utf-8編碼進行操作。

  在計算機中,”I‘m 傑克"的unicode字符集是這樣的編碼表:

I   0x49       
   0x27
m   0x6d
    0x200x67700x514b

  每個字符對應一個十六進制數(方便人們閱讀,0x代表十六進制數),但是計算機只能讀懂二進制數,所以,實際在計算機內表示如下:

I   0b1001001
   0b100111
m   0b1101101
    0b100000
傑   0b110011101110000
克   0b101000101001011

  由於Unicode規定,每個字符最少占用2個字節,所以,以上字符串在內存中的實際占位如下:
I   00000000 01001001
   00000000 00100111
m   00000000 01101101
    00000000 0010000001100111 0111000001010001 01001011

  這串字符總共占用了12個字節,但是對比中英文的二進制碼,可以發現,英文的前9位都是0,非常的浪費空間和流量。

看看utf-8是怎麽解決的:

I   01001001
   00100111
m   01101101
    0010000011100110 10011101 1011000011100101 10000101 10001011

  utf-8用了10個字節,對比Unicode,少了2個字節。但是,我們的程序中很少用到中文,如果我們程序中90%的內容都是英文,那麽可以節省45%的存儲空間或者流量。

所以,在存儲和傳輸時,大部分時候遵循utf-8編碼

技術分享圖片  技術分享圖片

四、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數據就會顯示相應的明文(包括英文和中文)

五、文件從磁盤到內存的編碼

當我們在編輯文本的時候,字符在內存對應的是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())

輸出:ascii

如果我們不想使用默認的解釋器編碼,就得需要用戶在文件開頭聲明了。還記得我們經常在python2.x中的聲明嗎?

#coding:utf-8

如果python2解釋器去執行一個utf-8編碼的文件,就會以默認的ASCII去解碼utf-8,一旦程序中有中文,自然就解碼錯誤了,所以我們在文件開頭位置聲明 #coding:utf-8,其實就是告訴解釋器,你不要以默認的編碼方式去解碼這個文件,而是以utf-8來解碼。而python3的解釋器因為默認utf-8編碼,所以就方便很多了。

參考資料

1. http://www.cnblogs.com/yuanchenqi/articles/5956943.html

2. http://www.cnblogs.com/284628487a/p/5584714.html

  

【轉】python基礎-編碼與解碼