標籤:aced 無法 unicode編碼 表示 區分 unicode 參考資料 image 參數
【轉自: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 ‘ 0x27m 0x6d 0x20傑 0x6770克 0x514b
每個字元對應一個十六進位數(方便人們閱讀,0x代表十六進位數),但是電腦只能讀懂位元,所以,實際在電腦內表示如下:
I 0b1001001‘ 0b100111m 0b1101101 0b100000傑 0b110011101110000克 0b101000101001011
由於Unicode規定,每個字元最少佔用2個位元組,所以,以上字串在記憶體中的實際佔位如下:
I 00000000 01001001‘ 00000000 00100111m 00000000 01101101 00000000 00100000傑 01100111 01110000克 01010001 01001011
這串字元總共佔用了12個位元組,但是對比中英文的二進位碼,可以發現,英文的前9位都是0,非常的浪費空間和流量。
看看utf-8是怎麼解決的:
I 01001001‘ 00100111m 01101101 00100000傑 11100110 10011101 10110000克 11100101 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 sysprint(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基礎-編碼與解碼