不知不觉中这篇文章成了我阅读量最高的文章。但是感觉自己写的不是很好。
如果大家感觉对自己帮助不大,可以去看下阮一峰大大的这篇文章:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
自始至终都没有捋一捋关于编码的问题,偶尔遇到问题就decode,encode解决了。
今天来整理一下关于编码的问题。如有错误还请大家指出。
编码
- 系统编码
我们都知道计算机存储信息都是以二进制的形式保存的,而且网络中信息的传输也都是以字节的形式进行传输的。那么我们看到汉字,中文都是怎么来的呢?说到这里大家可能想到了ASCII码表,ASCII码使用指定的7位或8位二进制数组合来表示128或256种可能的字符。如在ASCII表中 65对应的是字母A,那么某个值为65的字节或者字节串就代表了A。当然英文字母的表现使用一个字节就足够了,一个字节能表示的字符有256个。但是世界范围内的字符远远不止256个,于是就诞生了GB2312,GBK,unicode多种码表。其中unicode每个字符使用两个字节来表示,理论上能表示65536个字符,而且unicode包含各国大多数常用字符,被作为一种国际码表使用。这个码表就是系统所使用的码表。在存储信息或者读取信息的时候都是通过码表来进行的。不同的系统有着不同的默认码表, - Python编辑器编码
首先我们在编辑代码的时候肯定使用的是所在操作系统的码表。而我们在python文件开头声明的#coding=utf-8 是指python在读取代码的时候使用utf-8的编码方式读取。
下边会大概说一下utf-8与unicode的关系。python会有默认的编码(Python2是ascii,Python3是utf-8),这个默认编码是指对某个字符处理时使用的编码格式,但是对于文件读取,如果不指定编码格式的话,会使用操作系统默认的编码格式。
UTF-8 和 unicode的关系
Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
比如,汉字“严”的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。
表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,第一个问题是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,
而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,
每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,
这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:
对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
摘自https://www.cnblogs.com/csguo/p/7402121.html#4532275。
综上所述 utf-8 是unicode用来表现字符二进制的一种形式。举个列子
python2下:
#coding=utf-8
s = "小"
print(s.decode(encoding='utf-8'), type(s.decode(encoding='utf-8')))
print(s.decode(encoding='utf-8').encode(encoding='utf-8'), type(s.decode(encoding='utf-8').encode(encoding='utf-8')) )
输出为:
(u'u5c0f', <type 'unicode'>)
('xe5xb0x8f', <type 'str'>)
输出的第一行的u'u5c0f'十六进制代表十进制数23567。是指unicode码表中"小"对应的数值为233567,转化为二进制的形式是 10111000 0001111。
对照 Unicode符号范围 |UTF-8编码方式
# 0000 0000-0000 007F | 0xxxxxxx
#
# 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
#
# 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx10xxxxxx
#
# 0001 0000-0010 FFFF | 11110xxx 10xxxxxx10xxxxxx10xxxxxx
5c0f 处于第三栏位,所以UTf-8表现5c0f 需要三个字节。格式转化的标准为:unicode的两个字节倒着填进'x'中,按照从后向前的方式。
那么经过转化,10111000 0001111 ====> 11100101 10110000 10001111 ====> 229 176 143 ====> xe5xb0x8f
与第二行打印的byte符合。