無論是用Python還是其它語言,處理字符編碼都是一件極其痛苦的事情。我們無法忘記被UnicodeDecodeError和UnicodeEncodeError支配的恐懼。本文将以Python3為例,帶你了解Unicode的基本概念,以及字符串編碼解碼的工作原理,讓你從根本上理解字符編碼。
首先,我們來看一看什麼是字符編碼。我們知道,計算機裡所有的信息都是以數字的形式來表示的,字符也不例外。要想表示一個字符,首先要把它轉換成對應的數字。
最簡單的字符編碼就是大家耳熟能詳的ASCII碼。ASCII碼能夠表示127個字符,它們包括:大寫字母,小寫字母,标點符号,空格和一些非打印字符。每一個字符都對應一個代碼點(code point)。我們可以認為一個代碼點就是一個整數。ASCII碼中包含的字符和它們對應的代碼點範圍如下:
整個ASCII表包含128個字符。沒有出在這張表裡的字符無法用ASCII編碼來表示。
Python的string模塊裡定義了完整的ASCII字符集
我們可以在代碼中直接引用這些常量
ASCII編碼非常簡單,而且能夠表示所有英文字母和常見符号。但是這樣就夠了嗎?當然不是。如果我們想在計算機中表示一個漢字或者想要表示一個日語的假名該怎麼辦?很顯然,隻有128個字符的ASCII碼是遠遠不夠的。這就是Unicode産生的原因。
其實,Unicode和ASCII碼的目的是一樣的,隻不過Unicode所包含的字符要遠遠多于ASCII碼。事實上,Unicode最多可以容納1,114,112個code point。把世界上所有語言的文字和符号加起來應該也夠用了。比如說漢字“我”在Unicode中的編号是6211。為了與ASCII碼兼容,Unicode規定,前128個字符與ASCII碼是相同的。所以一個不大于128的code point所代表的Unicode字符與ASCII碼相同,而超過128的字符則為ASCII無法表示的。
由于Unicode的字符集太過龐大,因此,它無法像ASCII碼一樣,用一個字節就可以表示。所以,Unicode勢必要用多于一個字節來表示一個字符。這時就遇到一個問題,那就是在計算機進行讀取的時候,它怎麼知道那幾個字節是屬于一個字符的呢?比如,有一串字節數據“0xaa 0xbb 0xcc 0xdd 0xff”,我們怎麼知道哪幾個字節組合在一起來表示一個字符呢?那麼就需要一種約定,來告訴我們如何把code point轉換成字節流,或者反過來。這就是編碼和解碼。
既然是約定,那就意味着可以用不同的方法。事實上,最常用的編碼方式是UTF-8,除此之外還有UTF-16,UTF-32等。由于篇幅有限,這裡就不再展開每種編碼的具體細節了。大家隻需要知道,不管是什麼編碼,他們都是用來實現一個code point和一串字節流之間的轉換的。
在Python3中,str類型可以用來存儲可讀的Unicode文本,而bytes則用來存儲二進制數據。字符串編碼和解碼的過程就像這樣
例如:
這裡,str.encode()的輸出是一個bytes對象,其中保存了Unicode字符串編碼後的字節流。
這裡要注意的是,要想正确地對編碼數據進行解碼,必須使用匹配的編解碼方法,否則解碼的數據就會使錯誤的,比如下面這個例子:
可以看到,我們編碼的數據是一串希臘字母,但是由于解碼用的方法和編碼不一緻,所以接出來的居然是一串韓文字符,錯得有點離譜了。
總結
關注我,更多精彩文章!
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!