1. 什么是编码?
编码,准确点讲是字符编码,其实就是文本,数字,符号等各种各样的字符统一用数字来表示。
因为计算机只认识0和1,我们看到的各种字符,要让机器认识的话就必须先转换成数字,最后转换成可供机器识别的二进制即0和1。
所以字符编码就是二进制数据和字符之间的一道桥梁。
不同类型的编码,会将我们所认识的同一种字符用各自的方法转换成不同的二进制数据。
2. 编码有各种格式,它们之间的关系是什么样的?
在充分理解清楚字符编码的相关知识前,大多数人应该已经听说过ascii, gbk, unicode, utf-8等等各种编码。
由于计算机是美国人发明的,最开始他们只需要用到大小写字母,数字,符号和一些特殊的控制符。
一个字节八个比特的容量足够容纳这些数据了,还能多一位出来用作奇偶检验,这就是ascii编码的作用,它把0和1与上面提到的这些常用字符给联系了起来。
但是随着计算机的发展,各个国家都想出了自己的一套编码用于表示自己国家的字符,比如中国最开始的gb2312编码,其实就是用于解决中文字符的显示问题。
为了结束这种混乱的局面,国际组织就推出了Unicode字符集,基本上把所有常见字符都涵盖进去了,除了个别生僻字,这里就不作考虑了。
当然,一个字符的体积也从ascii编码的一个字节变成了两个字节。
这里我们当Unicode能表示所有字符,也就是说每个国家的每个字符都能在Unicode里找到对应的二进制形式,可以把它视作一种统一的编码规范。
但是,前面提到,ascii字符只需要一个字节,而Unicode却需要两个,所以Unicode在一定程度上大大增加了字符的存储空间。
因此,为了解决存储和网络传输过程中的问题,作为一种为unicode编码设计的在存储、传输时节省空间的编码方案,utf应运而生了!
3. 关于编码的应用
上面说到了这么多种编码方式,那具体应用的时候是个啥子情况呢?
为了方便后面讲解Python中的编码问题,这里先统一下叫法:
编码——encode——将字符形式转化成二进制数据
解码——decode——将二进制数据转化成字符形式
首先啊,我们要知道,任何数据被保存到计算机里——通常是存储在硬盘中,这时候都是二进制形式。
而到我们能看到它们的时候,它们通常是被加载在内存中,这时候它们是经过解码转换了的。
如果我们要把写入的文本存到硬盘上,就是在上面的步骤做个逆向操作,对输入的字符做编码,然后以二进制的形式存入硬盘。
上面两种可以简单的看成互逆操作,既然如此,其中用到的编码格式一定要统一。
比如说,很常见的一种情况:
我用记事本将一些文字以gbk的编码形式保存下来后,用其他编辑软件比如sublime text以utf或者其他编码形式去打开,自然会出现乱码问题。
4. Python中的编码问题
说起Python的编码问题,其实最容易诟病的地方主要发生在Python2时期。
我觉得有两点吧:
一是Python2中默认编码方式是ascii
如果在源文件中出现了中文或者一些其它字符,这时候就必须声明 #coding: utf8 或者 #coding: gbk
这样的源文件在运行过程中产生的字符也会是以该编码方式呈现
比如声明utf8的文件跑到windows文件下运行,输出的中文会出现乱码的情况
二是Python2中的字符串类型很值得诟病
2中的字符串类型准确的讲其实更像是“字节串”
熟悉的人可以看出来,这是字节类型,即bytes
而Python3中的字符串str,才是正儿八经的unicode类型,在任何地方都能吃得香
Python3中的默认编码也变成了utf8,再也不用因为中文而手动声明编码格式了
5. 了解了上面这些,我们再分析下日常使用过程中遇到的跟编码相关的问题:
1)Python操作文件时,读取出错
这里是因为我保存的时候用的utf-8编码,打开的时候,open函数在windows平台下默认是gbk编码打开,造成了冲突。解决方案是手动设置编码格式为utf-8。
类似的问题还有很多,其实只要搞清楚了文件操作过程中编码是扮演什么样的角色,熟悉些常见的编码类型,了解自己要操作的文件是什么类型的编码,熟用encode和decode等函数,就能顺利解决这一大类问题了。
2)
后续再补充...
写在最后
我用Python已经三年了,磕磕绊绊的学习过程中遇到过很多次跟编码相关的问题,这几天在工作中又遇到了,即使有先前的经验,处理时也不是一帆风顺。
我想了想,感觉自己还是没有吃透编码这个概念。
只有深入其中,搞明白编码是什么,为什么要有编码,实际场景又是什么样的,才能真正地去解决问题。
上面的文字都是我自己手敲的,虽然我觉得自己搞懂了,但是写出来肯定会有很多纰漏之处,希望有大佬看到了能够多多指点。
最后还是想说,遇到任何不熟悉的概念,凡事三问——是什么,为什么,怎么做。总是能搞明白的。
共勉