unicode 是 character set
- character set 是把每個(gè)字符對(duì)應(yīng)成數(shù)字的集合,,比如unicode中 A對(duì)應(yīng)0041,,漢字『我』對(duì)應(yīng) ‘6211’
- unicode 是個(gè)很大的集合,幾乎覆蓋世界上所有的字符,,現(xiàn)在的規(guī)模已經(jīng)可以容納100萬個(gè)字符,。
utf-8 是對(duì) unicode 存儲(chǔ)的實(shí)現(xiàn)方式
unicode 只定義字符對(duì)應(yīng)的數(shù)字,但沒有規(guī)定這些數(shù)字如何存儲(chǔ)起來,,比如像中文的『我』字存儲(chǔ)時(shí)需要兩個(gè)字節(jié)來表示,,而英文字母A卻只需要一個(gè)字節(jié),有些其他的字符可能需要3-4個(gè)字節(jié),。
- 如果統(tǒng)一規(guī)定每個(gè)字符用3個(gè)或者4個(gè)字節(jié)來存儲(chǔ),,那么每個(gè)英文字符都必然需要額外2到3個(gè)0,這對(duì)存儲(chǔ)是很大的浪費(fèi),。
- 如果每個(gè)字符按照實(shí)際需要的字節(jié)數(shù)來存儲(chǔ),,計(jì)算機(jī)就分不清三個(gè)字節(jié)是表示三個(gè)字符還是一個(gè)字符。
utf-8 是對(duì) unicode 編碼存儲(chǔ)的一種實(shí)現(xiàn)方式,,同樣的還有 utf-16, utf-32,。
utf-8 是使用最廣泛的編碼方式,采用變長的編碼方式,,可以使用1-4個(gè)字節(jié)來表示一個(gè)字符,; utf-16 用2個(gè)或4個(gè)字節(jié),utf-32 用4個(gè)字節(jié)表示,。編碼規(guī)則如下:
- 對(duì)于單字節(jié)的符號(hào),,字節(jié)的第一位設(shè)為0,,后面7位為這個(gè)符號(hào)的unicode碼。因此對(duì)于英語字母,, UTF-8編碼和ASCII碼是相同的,。
- 對(duì)于n字節(jié)的符號(hào)(n>1),第一個(gè)字節(jié)的前n位都設(shè)為1,,第n+1位設(shè)為0,,后面字節(jié)的前兩位一律設(shè)為10。剩下的沒有提及的二進(jìn)制位,,全部為這個(gè)符號(hào)的unicode碼,。
python2 中的 str 和 unicode
python2 中有字符串類型有兩種:byte string (str) 和 unicode string (unicode) 。
|
>>> s = '美的' >>> s '\xe7\xbe\x8e\xe7\x9a\x84' >>> s = u'美的' >>> s u'\u7f8e\u7684' >>> s = '美的' >>> s.decode('utf-8') u'\u7f8e\u7684' |
上面的輸出中,,第一個(gè)s的類型是 str,,打印出來的內(nèi)容是 utf-8 編碼過的內(nèi)容。第二個(gè)s的類型是 unicode,,打印出來的兩個(gè)雙字節(jié)的數(shù)字分別表示了兩個(gè)漢字『美的』,。
encode 和decode 提供 str 和 unicode 這兩種的類型的互相轉(zhuǎn)化。
- encode 把 unicode 轉(zhuǎn)化成 str(byte string)
- decode 把 str(byte string) 轉(zhuǎn)化成 unicode
本質(zhì)上,,str是存放的字節(jié)序,,有可能是 ascii, gbk, utf-8 等等中的任意一種,通過調(diào)用 decode 可以把他們轉(zhuǎn)化成 unicode ,,默認(rèn)的 decode 編碼是 ascii ,。str中到底是用的哪一種編碼,取決于它所在的場(chǎng)景,,跟 locale ,,文件編碼等等都有關(guān)系。
文本文件,、編輯器的處理
|
#!/usr/bin/env python # -*- coding: GBK -*- s = u'中文' print repr(s) print repr(s.encode('GBK')) |
比如上面的文件enc.py ,,保存的時(shí)候選擇文件編碼 是GBK,程序文件本質(zhì)上也是文件,,當(dāng)我們使用某個(gè)外部的應(yīng)用 打開它時(shí)(編輯器或者python解釋器等),,外部應(yīng)用是不知道該文件的編碼格式的,
這個(gè)時(shí)候有三種情況:
- 應(yīng)用使用其默認(rèn)的編碼方式去解析,,比如UTF-8或者ASCII,;python解釋器默認(rèn)是ASCII,編輯器可以自己設(shè)置,;
- 應(yīng)用根據(jù)文件中的字節(jié)內(nèi)容,,自動(dòng)檢測(cè)編碼方式;
- 文本文件告訴應(yīng)用使用什么編碼方式去解碼,;比如
# -*- coding: GBK -*- 告知解釋器使用GBK來解碼,;
試驗(yàn)一下,,把# -*- coding: GBK -*- 刪除后,執(zhí)行python enc.py ,,輸出:
|
File "enc.py", line 4 SyntaxError: Non-ASCII character '\xd6' in file enc.py on line 4, but no encoding declared; |
試著用vim打開該文件時(shí),,『中文』兩個(gè)字就會(huì)顯示成亂碼,因?yàn)関im默認(rèn)的文件編碼方式被設(shè)置成UTF-8了,。
|
#!/usr/bin/env python # -*- coding: GBK -*- s1 = u'中文' print repr(s1) print repr(s1.encode('GBK')) s2 = '中文' print repr(s2) print repr(s2.decode('GBK')) |
輸出結(jié)果:
|
u'\u4e2d\u6587' '\xd6\xd0\xce\xc4' '\xd6\xd0\xce\xc4' u'\u4e2d\u6587' |
從這里可以看出來,, s2中存放的是byte格式的從文件中讀到的GBK編碼的內(nèi)容。
再看下面的這段代碼,,程序文件utf8_enc.py ,保存成UTF-8編碼的,。
|
#!/usr/bin/env python # -*- coding: utf-8 -*- s1 = u'中文' print repr(s1) print repr(s1.encode('GBK')) s2 = '中文' print repr(s2) print repr(s2.decode('GBK')) |
輸出:
|
u'\u4e2d\u6587' '\xd6\xd0\xce\xc4' '\xe4\xb8\xad\xe6\x96\x87' Traceback (most recent call last): File "unicode_enc.py", line 12, in <module> print repr(s2.decode('GBK')) UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence |
這里同樣可以知道,,s2中存放的是文件保存的編碼UTF-8的byte碼。
References
http://www./the-differe…
http://www./blo…
https://docs./2/how…
http:///2012/bytes…
|