ASCII和Unicode和UTF 8和GBK
先說老大哥。我和很多人壹樣,在大學學習了這麽久,聽說過ASCII編碼這個名字。要說這個老大哥,先從字節說起。壹個字節由八位組成,每壹位代表0或1,壹個字節可以代表從00000000到1111111111 * * 2。ASCII碼使用壹個字節(不包括作為奇偶校驗位的字節的最高有效位)。ASCII碼實際上是用壹個字節中的7位來表示字符,* * *可以表示2 ^ 7 = 128個字符。比如當時用C語言寫程序時,往往需要記憶ASCII編碼中的0100001(即十進制65)來表示字符‘a’,0100001加上32後的0100065438。現在打開Python,調用chr和ord的函數,可以看到Python為我們改造了ASCII編碼。
第壹個00000000代表壹個空字符,所以ASCII編碼實際上只包括。
字母、標點符號、特殊符號等***127字符。因為ASCII誕生於美國,對於英文來說已經足夠了,英文是由字母組成,然後用文字表達。但是中國,日本,
其他語言的人,比如韓語,就不滿意。中文是壹個字壹個字的,ASCII編碼花了所有力氣。256個字符不夠。
所以後來出現了Unicode編碼。Unicode編碼通常由兩個字節組成,* * *表示256*256個字符,稱為UCS-2。有些孤立詞也用四個字節,稱為UCS-4。也就是說,Unicode標準還在發展中。然而,UCS-4是罕見的。我們先記住,原來的ASCII碼使用的是單字節碼,但是因為有很多不同語言的字符,所以人們使用的是兩個字節,於是出現了壹個覆蓋多種語言的統壹Unicode碼。
在Unicode中,ASCII中最初的127字符只需要在前面加壹個全零的字節。比如上面提到的字符‘a’:01100001,在Unicode中變成了000000001000065438。很快,美國人不高興了,吃了世界民族之林的壹鍋飯。以前用壹個字節傳輸的英語,現在變成了兩個字節,極大的浪費了存儲空間和傳輸速度。
人們再次使用他們的智慧,於是UTF-8編碼出現了。因為是針對空間的浪費,這種UTF 8編碼是長度可變的,從壹個字節的英文字母到三個字節的中文,再到六個字節的壹些生僻字。解決了空間問題,UTF-8編碼還有壹個神奇的附加功能,兼容老大哥的ASCII編碼。壹些古董軟件現在可以在UTF-8編碼中繼續工作。
請註意,除了英文字母相同之外,中文字符在Unicode編碼和UTF-8編碼中通常是不同的。例如,Unicode中的漢字“中”是01001110。
00101101,而在UTF-8編碼中是1100101065438。
10101101。
我們的祖國母親自然有她自己的壹套標準。即GB2312和GBK。當然現在很少了。UTF-8通常直接使用。記得唯壹壹次看到GB編碼的網頁,是成人網站。
Python3中的默認編碼
Python3中的默認值是UTF-8,我們傳遞以下代碼:
導入系統
sys.getdefaultencoding()
可以查看Python3的默認編碼。
Python3中的編碼和解碼
Python3中的字符編碼經常使用Decode和encode函數。尤其是在抓取網頁時,熟練使用這兩個功能是非常有益的。我的理解,encode的作用,是使我們看到的直觀的字符,在計算機中轉換成字節形式。而Decode則是把字節形式的字符轉換成我們能理解的、直觀的、“人”的形式。如下圖。
\x表示十六進制,\xe4\xb8\xad表示二進制1100100101011000。
10101101。也就是說,漢字“中”的編碼是字節形式的,即11001001011000。
10101101。同樣,我們取11100100。
101110001101,也就是\xe4\xb8\xad回來解碼,就是漢字'中'。完整的字符串應該是b'\xe4\xb8\xad '。在Python3中,字節形式的字符串必須以B為前綴,B以上面b'xxxx '的形式書寫。
如上所述,Python3的默認編碼是UTF-8,所以我們可以看到Python在UTF-8中處理這些字符。所以從上圖可以看出,即使我們通過encode('utf-8 ')將字符encode編碼為UTF-8,結果還是壹樣的:b'\xe4\xb8\xad '。
知道了這壹點,又知道了UTF-8兼容ASCII,我們就可以猜測我們大學經常背的‘A’對應的是ASCII中的65,在這裏是否可以正確解碼。十進制65到十六進制是41,我們來試試:
b'\x41 '。解碼()
結果如下。果然是字符‘a’
Python3中的編碼轉換
據說字符在計算機內存中統壹用Unicode編碼。只有當字符要被寫入文件、存儲在硬盤中或從服務器發送到客戶機時(如網頁前端的代碼),它才成為utf-8。但其實我更關心的是如何把這些字符用Unicode字節的形式表達出來,揭示它在內存中的積極用途。這裏有壹面魔鏡:
xxxx . encode/decode(' unicode-escape ')
輸出如下所示
B'\\u4e2d '還是b'\u4e2d,壹個斜杠好像沒關系。同時我們可以發現,在shell窗口中,直接輸入' \u4e2d '和輸入B' \u4e2d '。decode('unicode-escape ')都壹樣,會打印漢字'中',但是' \ U4E2D '。decode ('Unicode-escape ')將給出壹個錯誤。描述Python3不僅支持Unicode,而且可以識別壹個' \ uxxxxx '格式的Unicode字符並等價於str類型。
如果我們知道壹個Unicode字節碼,它怎麽能變成UTF-8字節碼呢?了解了以上,現在有了壹個思路,先解碼,再編碼。代碼如下:
xxx.decode('unicode-escape ')。編碼()
測試如下:
妳可以看到最終輸出的UTF 8字節和上面的壹樣。嘗試成功了。所以其他代碼之間的轉換大概也是這樣。
最終擴展
記住剛才的順序時代變了,老大哥ASCII被合並了,但是順序還是有用的。Try ord ('medium '),輸出結果為20013。20013是什麽?我們再試試hex(ord ('Zhong ')),輸出結果是' 0x4e2d ',也就是20013就是上面我們遇到過無數次的x4e2d的十進制值。這裏先說壹下hex,這是壹個用來轉換成十六進制的函數。學過單片機的人,肯定對hex很熟悉。
最後,網上看到的別人問題的擴展。我們寫' \u4e2d '這樣的字符,Python3知道我們想表達什麽。但是當Python讀取壹個文件時,' \u4e2d '出現。電腦認不出來嗎?後來,下面有人給出了答案。如下所示:
導入編解碼器
file = codecs.open( "a.txt "," r "," unicode-escape ")
u = file.read()
打印(u)