用 Python 理清编码问题:Unicode万国码
Unicode——万国码
为解决语言各自为政的编码,人们提出了Unicode编码方案,这个方案简单粗暴:把世界上所有语言字符统一编码。Unicode的两种方案UCS-2和UCS-4,可使用空间分别达到2^16和2^32个:外星人到访地球之前,应该是够用的。
我们看几个字符的Unicode编码码位(code point)是怎样的:
ls = 'abAB巩★☆'
print([ord(l) for l in ls])
结果:[97, 98, 65, 66, 24041, 9733, 9734]。可见,字母abAB的Unicode码位和其ASCII码位一致,所以字符为字母时两者兼容,而汉字巩的码位为24041(0x5de9),与之前的GB系列编码47534(0xb9ae)不同,所以Unicode和GB系列编码之间是不完全兼容的:只有ASCII部分兼容。
所有国家的人都使用Unicode编码之后,扩展、乱码问题都不复存在:所有人类语言字符都有了一个统一的编码码位,沟通中我们写出的每个数字编码,都有唯一的字符与他对应。Python中chr函数返回Unicode码位对应的字符。
>>> print([chr(i) for i in [123,957,24041]])
['{', 'ν', '巩']
>>> ls = 'abAB巩★☆'
>>> ls.encode('Unicode')
Traceback (most recent call last):
File "<stdin>", line 1, in <module> LookupError: unknown encoding: Unicode
UTF-32 四字节为单位
>>> 'aA巩'.encode('utf-32LE')
b'a\x00\x00\x00A\x00\x00\x00\xe9\x5d\x00\x00'
UTF-16 两字节为单位
>>> 'aA巩'.encode('utf-16LE')
b'a\x00A\x00\xe9\x5d'
>>> 'aA巩'.encode('utf-16BE')
b'\x00a\x00A\x5d\xe9'
《格列佛游记》中,小人国国民为吃鸡蛋先吃大头或小头,针锋相对,组成了两个军事对立集团big endians和little endians,相互间多次发动战争。
UTF-8 变长字节编码
>>> 'aA巩'.encode('utf-8')
b'aA\xe5\xb7\xa9'
UTF-8 编码转换规则
0x00-0x7F之间的码位,兼容ASCII码,单字节直接存储在以下模板 0*** **** 0x80-0x7ff之间,使用两个字节存储,字节模板是110* **** 10** **** 0x800-0xffff之间,使用三个字节存储,字节模板是1110 **** 10** **** 10** **** 0x10000-0x1fffff之间,使用四个字节存储,字节模板是1111 0*** 10** **** 10** **** 10** ****
UTF三种编码后的长度
es = 'abcdefghij'
cs = '莫愁前路无知己,天下谁人不识君。'
codes = ['utf-32le','utf-16le','utf-8']
print([len(es.encode(code)) for code in codes])
print([len(cs.encode(code)) for code in codes])
总结
Unicode统一了世界各语言字符。Unicode几种编码形式中; UTF-32简单,但浪费严重。 UTF-16使用两个字节为单位存储,节省了空间。 UTF-8使用一个字节直接存储,是效率、空间的平衡。
作者:巩庆奎,大奎,对计算机、电子信息工程感兴趣。gongqingkui at 126.com
赞 赏 作 者
更多阅读
特别推荐
点击下方阅读原文加入社区会员
评论