通過例子來看問題是比較容易懂的。
首先來看,下面這個是我新建的一個txt文件,名字叫做ivan_utf8.txt,然后里面隨便編輯了一些東西。
然后來用控制台打開這個文件,同樣也是截圖:
這里就是簡單的打開文本,讀取文本內容,打印出來看,我們看到print出來的是和我寫進去的是一樣的東西。然后呢,我在對這個內容使用decode(‘gbk’),就是解編碼,使用gbk方式進行解碼,什么意思呢?就是說,我假設這個a是gbk方式的編碼,結果是什么呢?大家都看到了,報錯了哈!!!!說明這個不是gbk編碼,是的,我的編碼是utf-8編碼,當然要報錯啦。。。其實主要是這個里面的中文無法識別,如果只有英文應該還是不會報錯的,雖然解出來內容是變樣了哈。。。
回到我們這個問題,這個報錯是什么意思呢?
這就是牽扯到我們今天要講的問題了,看完我講完的內容就能夠知道是為什么了。。。
1.python字符串的本質是什么呢?
2.unicode的神奇之處在哪里?
3.python2是怎樣處理unicode編碼的?
4.python3是怎樣處理unicode編碼的?
1.為什么python用unicode編碼呢?
主要有:
1.處理非英文的內容;
2.可以使用第三方庫;
3.接受任何的輸入內容;
在網頁應用和數據庫的交互以及命令行腳本處理都可以用到python。
上面這個報錯的例子就是命令行腳本的例子。
大家都知道,其實就是一串字節流(1byte:字節),一個字節就是8位二進制數,10進制的8位是千萬,這個二進制的8位就叫做1個字節。1個二進制位只能夠表示0或者1。所以1個字節可以表示2的8次方種可能。扯遠了。。。。。。。
我們這個字符串時utf-8編碼方式編碼的。什么叫編碼方式呢?就是說這么一串01010101010101……是按照什么樣的規則轉換成字符的,為什么顯示出來會像我們看到的一樣?
utf-8就是其中一種規則。
unicode編碼每一個字符占兩個字節,也就是16個bit位咯!!!如果是其他編碼的話,這16bit位可能表示的別的內容。
如今python標准庫已經支持100多種編碼方式了。
我們不用print,直接a就會看到原始的內容:’sdfs\xe5\xae\xb6\xe9\x87\x8c\xe5\x8f\x91\xe7\x94\x9f\xe7\x9a\x84\xe7\xba\xa0\xe7\xba\xb7'
這個就是在內存中的表示方式,前面的英文可以顯示出來,后面的因為是中文,不能夠直接翻譯出來,人家也不會嘛。。。這些都是16進制,4個2進制只需要1個16進制咯。
utf-8是asciil編碼的一種擴展。每個字符是一個字節。所以一個有2的8次方 (2的平房為4,4次方為16,6次方64,8次方就是256),因為是256種可能。但是為什么標准教程上說是128呢?這個等我回去查一下資料再說吧。。可能是ascii庫只有128種字符,還有一半的就浪費了哦。
非英文的就不能用ascii來編碼,比如說:d = ‘廖’,然后d.encode(d),這樣就會爆下面的錯:
>>> d.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)
在python中:類型關系如下:
<type 'basestring'>
|
+--<type 'str'>
|
+—<type’unicode'>
對字符串a使用decode(encoding)就會得到unicode類型,a為unicode類型的時候a.encode(encoding)就會得到str類型了。
>>> print a
sdfs家里發生的糾紛
>>> len(a)
25
>>> a[-1]
‘\xb7'
>>> a_uni = a.decode('utf-8')
>>> a_uni
u'sdfs\u5bb6\u91cc\u53d1\u751f\u7684\u7ea0\u7eb7'
>>> type(a_uni)
<type 'unicode'>
>>> len(a_uni)
11
>>> a_uni[-1]
u’\u7eb7'
unicode是:
一種不用字節的形式來表示文本;就是說是變長的,len就是個數。
每次中語言的每一個字符都有唯一的數字來表示。
支持所有主流的語言;
可以表示超過100萬的符號;
如果ascii, utf-8 和其他的字節串 是文本,那么unicode就是文本性的,unicode時最嚴格的文本格式;unicode是最嚴格的。這是文字的抽象格式。
unicode是一種概念:
為unicode保存到硬盤,就必須進行編碼
>>> a = unicode('AB')
>>> type(a)
<type 'unicode'>
>>> a.encode(‘utf-8’)#這就是編碼成了utf-8編碼了。
'AB'
utf-8
就是變量的多字節表示。
前128個字符就和ascii一樣。(其他的1字節表示不了,需要更多字節,一個字符可能需要1-4個字節)
>>> a = unicode('AB')
>>> a.encode('utf-16')
‘\xff\xfeA\x00B\x00’
utf-16
多字節表示。
2-4個字節表示一個字符;
是對2個字節范圍內的字符舉行優化;
utf-32
固定寬度的字符,最快
4個字節32位表示一個字符;
python不支持
解碼文字轉換為unicode
大多數情況都是自動的。
這種情況主要發生在第三個庫。
python會為你解碼的。
往一個ascii編碼格式的文件里寫入unicode編碼的文字時會報錯的。
如果要寫,可以先將字符a.encode(sys.getdefaultencoding())
python2的默認方式是ascii
可以用:sys.setdefaultencoding(‘utf-8’)來設置python的編碼方式。這個設置當次有效。
但是設置會有更多的麻煩。
解碼:
1.解碼
2.unicode編碼無處不在
3.編碼
轉換為unicode:
def to_unicode_or_bust(obj, encoding = ‘utf-8’):
if isinstance(obj, basestring):
if not isinstance(obj, unicode):
obj = unicode(obj, encoding)
return obj
轉換為str類型:
主要用在寫入磁盤活着print出來的時候:
直接encode(encoding)即可。
open文件指定編碼方式,在第三個參數:
f = open(’1.txt’, ‘r’, encoding = ’utf-8’)
content = f.read()
f.close()
這樣就是utf-8的方式讀了。寫也是一個道理。