基础知识
计算机只能处理0和1两个数字,所以所有的数据(文本、图像)必须变成0和1这样的数字。
ASCII编码
计算机是美国人发明的,所以最早只有127个字符被编写进计算机,也就是常见的阿拉伯数字,字母大小写,以及键盘上的符号。这被称为ASCII编码。比如A的ASCII编码为65,65再转换为01000001,这才是计算机处理的东西。
各个国家自己的编码
中国制定了GB2312编码,兼容ASCII编码,那么假设61,62,63在GB2312编码中对应的为慕课网三个字,在ASCII码表中对应的是A,B,C,在Shift_JIS(日本的编码)对应的是ハロー,那么中国的文本用GB2312编码,存储到计算机中为一串01数字,日本人使用Shift_JIS解码后,读到的就全是一串看不懂的日文乱码,甚至无法解析的二进制码。
Unicode编码
后来有了Unicode编码,它将全世界几乎所有的语言进行了汇总,使用了同一种编码,这样大家都使用同一种编码来进行编码、解码,就会最终得到正确的文字。
UTF-8编码
但是由于Unicode编码是使用16个数字位来进行的编码,太过占用资源,所以就有了UTF-8编码,这种编码使用8个数字位来进行存储,遇到中文会使用两个8位编码来存储。大大避免了浪费空间
计算机中的文字存储
所以记事本中的文字(如中文),使用Unicode来编码,存储到计算机中时,会再次被编码为UTF-8,在我们打开时,会先从UTF-8编码转为Unicode编码,再从Unicode编码转为各自国家的编码
网络之间的文字传输
服务器上的Unicode数据读取出来后,转为UTF-8编码(节省带宽),传输给浏览器,
Python3
Python3字符串默认使用Unicode编码所以Python3支持多国语言;
以Unicode表示的str通过encode()可以编码为指定的bytes
如果bytes使用了ASCII编码,遇到ASCII码表没有的字符会以\x##表示,此时使用‘\x##‘.decode(‘对应编码‘)解码即可
>>> import chardet >>> str=‘中国a‘ # utf-8编码 >>> str.encode(‘utf-8‘) b‘\xe4\xb8\xad\xe5\x9b\xbda‘ >>> chardet.detect(str.encode(‘utf-8‘)) {‘encoding‘: ‘utf-8‘, ‘confidence‘: 0.7525, ‘language‘: ‘‘} >>> str.encode(‘utf-8‘).decode(‘gbk‘) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xad in position 2: illegal multibyte sequence >>> str.encode(‘utf-8‘).decode(‘utf-8‘) ‘中国a‘ # gb2312 / gbk编码 >>> str.encode(‘gb2312‘) b‘\xd6\xd0\xb9\xfaa‘ >>> str.encode(‘gbk‘) b‘\xd6\xd0\xb9\xfaa‘ >>> chardet.detect(‘中国我爱你啊啊啊啊啊啊啊哈哈哈哈啊哈哈哈哈哈哈‘.encode(‘gb2312‘)) {‘encoding‘: ‘IBM855‘, ‘confidence‘: 0.3697632002333717, ‘language‘: ‘Russian‘} >>> chardet.detect(str.encode(‘gbk‘)) {‘encoding‘: ‘IBM855‘, ‘confidence‘: 0.6143757788492946, ‘language‘: ‘Russian‘} # chardet识别仅在文字具有一定长度和一定复杂度时才可以识别正确 >>> chardet.detect(‘中国我爱你啊啊啊啊啊啊啊哈哈哈哈我是一只小小鸟‘.encode(‘gb2312‘)) {‘encoding‘: ‘GB2312‘, ‘confidence‘: 0.7142857142857143, ‘language‘: ‘Chinese‘} >>> str.encode(‘gbk‘).decode(‘IBM855‘) ‘ол╣Щa‘ >>> str.encode(‘gbk‘).decode(‘utf-8‘) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xd6 in position 0: invalid continuation byte >>> str.encode(‘gbk‘).decode(‘gbk‘) ‘中国a‘