当python要做编码转换的时候,会借助于内部的编码,转换过程是这样的:
原有编码 -> 内部编码(UNICODE) -> 目的编码
\xa0
是不间断空白符
我们通常所用的空格是 \x20
,是在标准ASCII可见字符 0x20~0x7e 范围内。
而 \xa0
属于 latin1 (ISO/IEC_8859-1)中的扩展字符集字符,代表空白符nbsp(non-breaking space)。
latin1 字符集向下兼容 ASCII ( 0x20~0x7e )。通常我们见到的字符多数是 latin1 的,比如在 MySQL 数据库中。
这里也有一张简陋的Latin1字符集对照表。
\u3000
是全角的空白符
根据Unicode编码标准及其基本多语言面的定义, \u3000
属于CJK字符的CJK标点符号区块内,是空白字符之一。它的名字是 Ideographic Space ,有人译作表意字空格、象形字空格等。顾名思义,就是全角的 CJK 空格。它跟 nbsp 不一样,是可以被换行间断的。常用于制造缩进, wiki 还说用于抬头,但没见过。
这里还有一个 Unicode.org 上关于 CJK 标点符号块的字符代码表。
在读取文件的时候,可以让codecs来代劳。
codecs读文件
results.txt
两部委:到2020年底重点城市生活垃圾得到有效分类(图)
英雄惜英雄! 传奇为格策叫冤:已尽力不应被批
中华关爱失能老兵和老人公益行活动启动仪式在京举行(组图)
国安酷暑作战满意拿分 谢峰:上半场少补一次水
国内首家省级民营投资平台在无锡揭牌成立
5月外汇供求进一步趋向平衡 跨境资金流出压力缓解
#-*- coding: UTF-8 -*-
import codecs
# 第三个参数可以为r只读 w只写 a附加 r+读写
cf = codecs.open("results.txt", "r", "UTF-8")
s = cf.read()
print s.encode("GBK", 'ignore')
cf.close()
如果报以下错误:
UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 268: illegal multibyte sequence
是因为Windows cmd默认是GBK(CP936)编码,有部分Unicde的字符无法编码为GBK,所以可以把这些字符替换为空格,或者忽略掉。
方式1:string.replace(u'\xa0', u' ')
方式2:print "非法字符\xa0".encode("GBK", 'ignore');
codecs从UTF-8转换为GBK格式
#-*- coding: UTF-8 -*-
import sys
reload(sys)
# 设置系统默认编码
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编码的字符串转换为GBK编码,并忽略掉无法编码的字符。
cwf.write(s.encode("gbk", 'ignore'))
cwf.flush()
cwf.close()
如果不加sys.setdefaultencoding(“gbk”)报错:
使用编码器
#-*- coding: UTF-8 -*-
import codecs
# 创建gb2312编码器
cgb = codecs.lookup("gb2312")
# 创建utf-8编码器
# lookup函数返回一个包含四个元素的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 = "我爱北京天安门"
print len(stest), stest, type(stest)
# 21 鎴戠埍鍖椾含澶╁畨闂?<type 'str'>
# 从单字节到多字节叫做decoding
utest = cutf8.decode(stest)
# (u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8', 21)
print utest[0], type(utest[0])
# 我爱北京天安门 <type 'unicode'>
# 从多字节到单字节叫做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])
# 我爱北京天安门 <type 'str'>
从单字节到多字节叫做decoding,从多字节到单字节叫做 encoding。
为什么从 unicode 转 str 是 encode,而反过来叫 decode?
因为 Python 认为 16 位的 unicode 才是字符的唯一内码,而大家常用的字符集如 gb2312,gb18030/gbk,utf-8,以及 ascii 都是字符的二进制(字节)编码形式。把字符从 unicode 转换成二进制编码,当然是要 encode。
反过来,在 Python 中出现的 str 都是用字符集编码的 ansi 字符串。Python 本身并不知道 str 的编码,需要由开发者指定正确的字符集 decode。