-
Python学习笔记:字符编码原理和操作详解
一、电脑字符集的历史
1、电脑是如何将二进制与字符对应起来的?
我们知道,电脑底层只认识0和1的二进制数据,为了让电脑可以跟人类互动,我们使用8个二进制位(即1个字节)来对应一个更复杂的数字,
比如:使用二进制“01000001”来指代十进制“65”,也就是大写字母A
实际使用场景中,人类利用键盘打字符“A”时,实际上是打65这个数字,电脑再到表中寻找65所代表的二进制数据“01000001”,实际处理的是这个二进制数据,这样就对应起来了,
这种对应关系表就是最早的字符编码集ASCII码表,如下图:
2、字符集是如何发展成一个庞大家族的?
电脑最初是西方人发明的,欧美国家的字符比较少,他们仅占用了前面127个位置就已经够用了,而8位的二进制数据最多可以表示255个不同的字符,剩下的128个字符就留给了别的国家,那么别国肯定是不够用的,怎么办?
于是聪明的中国人在ASCII码中规定几个位置,默认当电脑要寻找这几个位置的字符时就映射到另外一张表格中,而这张表格中存储了完整的中文字符,中文字符的发展历史如下:
a、GB2312:支持7000个汉字
b、GBK1.0:支持20000+个中文字符
c、GB18030:支持27000+个中文字符
d、Unicode:由于当时各国都发展出了自己的字符集,非常的混乱,于是国际标准组织统一将各国的字符集又整合成一个大字符集,即Unicode万国码,所有字符都至少占2个字节
e、UTF-8:这是Unicode的扩展集。使用了Unicode以后,西方人发现,自己原来的ASCII仅占1个字节,现在却需要至少2个字节存储,这样让原来的文件大了一倍,所以不干了,为了兼容原来的ASCII就有了UTF-8,规定英文字符依然是1字节,其他字符是3字节存储。
3、乱码问题是怎么产生的?
因为编码集繁多,不同编码集之间没有对应关系。比如中文和日文字符中都有“酒”这个字,但是在中文编码集中可能对应的是50这个数字,而日文中则对应的是100,那么如果将中文软件放在日文电脑中执行就会出现乱码。
所以产生乱码的根本原因有两点:
a、编码集中找不到这个编码:比如有些国家的字符异常的多,在该国编码集中对应30000的字符,在中文GB2312中可能就没有相应的字符,于是就无法显示。
b、编码集中对应到错误的编码:就算两个编码集中都有30000这个字符,但是因为编著的时候各自的数字对应的字符是不同的,所以也会造成乱码。
二、Python操作字符集
1、python2/python3中如何处理编码问题?
python3中默认是Unicode解码方式的,也就是说无论你的py文件是用何种编码格式,python3都默认将用Unicode重新解码,所以在py文件头部要声明编码格式,以告诉python3该文件的编码格式,请python3将文件解码成Unicode中对应的编码集
比如:py格式是用GBK编码的,python3在编译的时候会用Unicode来解码,这样就会报错,因为GBK的编码格式跟Unicode不同,你需要声明你使用的是GBK编码格式,然后python3再将GBK转成Unicode中对应的GBK集,这样就没问题了。
在pycharm中一般将编码全部改成utf-8即可,这样一来,编码是用uft-8,解码是Unicode,因为uft-8是Unicode的扩展集,是可以互相转换的,不会报错。如下图:
python2中也是一样的道理,不过python2中默认是用ASCII码解码的,所以如果你的py文件是用别的字符集编码的,则需要在头部声明编码格式,这样python2才会用对应的方式解码。
不声明编码方式的情况,在文件中出现中文,编译时就会报错!
2、不同编码集之间怎么转换?
因为Unicord涵盖了所有编码集,所以只需要先解码成Unicord,这样就可以达到两个编码集互相转换的目的。
比如:中文gbk要转成uft-8,电脑则需要先找到gbk对应的Unicord中的对应编码(从gbk解码成Unicord),然后从Unicord编码成utf-8,即可。如下图:
3、python3中怎么用代码处理编码?
a、encode("coding"):即编码。将文本编码成指定的编码,返回该编码的字节码,参数coding是你想要编码的编码集。
b、decode(“coding”):即解码。将文本解码成Unicode编码集中对应的编码集,参数coding是告诉decode方法你之前用的是什么编码格式,如果不告知则无法从Unicode中找到对应的编码集。
比如:str1.decode(“gbk”),即,str1我之前是用gbk格式编码的,decode请你将我解码成Unicode中对应的gbk编码,
注意:gbk编码和Unicode中对应的gbk编码是不同的概念,因为Unicode已经重新将gbk编码过了,所以编码格式肯定是不同的,我们要将gbk解码成Unicode中的gbk,
就是为了能让Unicode起到兼容作用,这样在别的支持Unicode的电脑上也可以显示,不会乱码。
c、将gbk转utf-8,具体代码如下:
str1.decode("gbk").encode("utf-8")
d、将utf-8转gbk,具体代码如下:
str1.decode("utf-8").encode("gbk")
三、总结
总的来说,有3个要点:
1、你用什么编码集编码的,就要用什么编码集编码,比如:你用的是gbk编码,那么在解码的时候也要选择gbk,不然就会乱码或者不能解析报错
2、不同编码集之间的转换是通过Unicode编码集转换的,比如:你用gbk编码的要转成utf-8,就先要将gbk解码成Unicode中对应的gbk编码,然后再转成utf-8
3、如果解码的时候不知之前的编码格式,那么就会报错,需要先给定你的编码方式,然后解码成Unicode中对应的编码集