當(dāng)python要做編碼轉(zhuǎn)換的時(shí)候,會(huì)借助于內(nèi)部的編碼,轉(zhuǎn)換過(guò)程是這樣的:
原有編碼 -> 內(nèi)部編碼(UNICODE) -> 目的編碼
\xa0
是不間斷空白符
我們通常所用的空格是 \x20
,是在標(biāo)準(zhǔn)ASCII可見(jiàn)字符 0x20~0x7e 范圍內(nèi)。
而 \xa0
屬于 latin1 (ISO/IEC_8859-1)中的擴(kuò)展字符集字符,代表空白符nbsp(non-breaking space)。
latin1 字符集向下兼容 ASCII ( 0x20~0x7e )。通常我們見(jiàn)到的字符多數(shù)是 latin1 的,比如在 MySQL 數(shù)據(jù)庫(kù)中。
這里也有一張簡(jiǎn)陋的Latin1字符集對(duì)照表。
\u3000
是全角的空白符
根據(jù)Unicode編碼標(biāo)準(zhǔn)及其基本多語(yǔ)言面的定義, \u3000
屬于CJK字符的CJK標(biāo)點(diǎn)符號(hào)區(qū)塊內(nèi),是空白字符之一。它的名字是 Ideographic Space ,有人譯作表意字空格、象形字空格等。顧名思義,就是全角的 CJK 空格。它跟 nbsp 不一樣,是可以被換行間斷的。常用于制造縮進(jìn), wiki 還說(shuō)用于抬頭,但沒(méi)見(jiàn)過(guò)。
這里還有一個(gè) Unicode.org 上關(guān)于 CJK 標(biāo)點(diǎn)符號(hào)塊的字符代碼表。
在讀取文件的時(shí)候,可以讓codecs來(lái)代勞。
codecs讀文件
results.txt
兩部委:到2020年底重點(diǎn)城市生活垃圾得到有效分類(圖)
英雄惜英雄! 傳奇為格策叫冤:已盡力不應(yīng)被批
中華關(guān)愛(ài)失能老兵和老人公益行活動(dòng)啟動(dòng)儀式在京舉行(組圖)
國(guó)安酷暑作戰(zhàn)滿意拿分 謝峰:上半場(chǎng)少補(bǔ)一次水
國(guó)內(nèi)首家省級(jí)民營(yíng)投資平臺(tái)在無(wú)錫揭牌成立
5月外匯供求進(jìn)一步趨向平衡 跨境資金流出壓力緩解
#-*- coding: UTF-8 -*-
import codecs
# 第三個(gè)參數(shù)可以為r只讀 w只寫 a附加 r+讀寫
cf = codecs.open("results.txt", "r", "UTF-8")
s = cf.read()
print s.encode("GBK", 'ignore')
cf.close()
如果報(bào)以下錯(cuò)誤:
UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 268: illegal multibyte sequence
是因?yàn)閃indows cmd默認(rèn)是GBK(CP936)編碼,有部分Unicde的字符無(wú)法編碼為GBK,所以可以把這些字符替換為空格,或者忽略掉。
方式1:string.replace(u'\xa0', u' ')
方式2:print "非法字符\xa0".encode("GBK", 'ignore');
codecs從UTF-8轉(zhuǎn)換為GBK格式
#-*- coding: UTF-8 -*-
import sys
reload(sys)
# 設(shè)置系統(tǒng)默認(rèn)編碼
sys.setdefaultencoding("gbk")
import codecs
crf = codecs.open("results.txt", "r", "UTF-8")
s = crf.read()
crf.close()
cwf = codecs.open("out.txt", "w", "gbk")
print type(s)
# 把UTF-8編碼的字符串轉(zhuǎn)換為GBK編碼,并忽略掉無(wú)法編碼的字符。
cwf.write(s.encode("gbk", 'ignore'))
cwf.flush()
cwf.close()
如果不加sys.setdefaultencoding(“gbk”)報(bào)錯(cuò):
使用編碼器
#-*- coding: UTF-8 -*-
import codecs
# 創(chuàng)建gb2312編碼器
cgb = codecs.lookup("gb2312")
# 創(chuàng)建utf-8編碼器
# lookup函數(shù)返回一個(gè)包含四個(gè)元素的TUPLE
cutf8 = codecs.lookup("utf-8")
print cutf8[0]
# <built-in function utf_8_encode>
# 同 codecs.getencoder("utf-8")
print cutf8[1]
# <function decode at 0x0000000002A20978>
# 同 codecs.getdecoder("utf-8")
print cutf8[2]
# encodings.utf_8.StreamReader
# 同 codecs.getreader("utf-8")
print cutf8[3]
# encodings.utf_8.StreamWriter
# 同 codecs.getwriter("utf-8")
stest = "我愛(ài)北京天安門"
print len(stest), stest, type(stest)
# 21 鎴戠埍鍖椾含澶╁畨闂?<type 'str'>
# 從單字節(jié)到多字節(jié)叫做decoding
utest = cutf8.decode(stest)
# (u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8', 21)
print utest[0], type(utest[0])
# 我愛(ài)北京天安門 <type 'unicode'>
# 從多字節(jié)到單字節(jié)叫做encoding
gtest = cgb.encode(utest[0])
# ('\xce\xd2\xb0\xae\xb1\xb1\xbe\xa9\xcc\xec\xb0\xb2\xc3\xc5', 7)
print gtest[0], type(gtest[0])
# 我愛(ài)北京天安門 <type 'str'>
從單字節(jié)到多字節(jié)叫做decoding,從多字節(jié)到單字節(jié)叫做 encoding。
為什么從 unicode 轉(zhuǎn) str 是 encode,而反過(guò)來(lái)叫 decode?
因?yàn)?Python 認(rèn)為 16 位的 unicode 才是字符的唯一內(nèi)碼,而大家常用的字符集如 gb2312,gb18030/gbk,utf-8,以及 ascii 都是字符的二進(jìn)制(字節(jié))編碼形式。把字符從 unicode 轉(zhuǎn)換成二進(jìn)制編碼,當(dāng)然是要 encode。
反過(guò)來(lái),在 Python 中出現(xiàn)的 str 都是用字符集編碼的 ansi 字符串。Python 本身并不知道 str 的編碼,需要由開(kāi)發(fā)者指定正確的字符集 decode。