本节重点:
为什么计算机需要编码?
编码/解码的概念
计算机编码的发展历程
乱码问题是怎样产生的?
Python编码转换
一、为什么计算机需要编码?
首先我们知道,计算机只能识别0和1的组合(对应电流开和关),所以大家熟稔的一句话是计算机只能处理二进制。
既然计算机只能处理二进制,那么意味着计算机就只能处理数字(比如说想将9存储进计算机,则需要将9转换为二进制进行存储),但是对于非数字的字符,也同样有存储需求。
为了解决这个问题,聪明的人类发明了数字与字符的对照关系,即固定的数字一一对应着固定的字符,这套标准的对照关系,在最早就叫做ASCII表。
有了这套对照关系,那么就能实现人类可理解的字符与计算机之间的沟通。举个例子来说:依照ASCII的对照关系,人在键盘上输入字母A的时候,实际上是给计算机传输了一个数字65,计算机输出66的时候,实际上是输出了字母B。
二、编码/解码的概念
编码:将内容存储进计算机存储器的过程叫编码
解码:从计算机存储器将内容读取出来的过程叫解码
字符:编码表里面的每个符号称为字符
字符集:整个字符编码里面涉及到的所有的字符称为字符集
字符码:每个字符对应的数字成为字符码
计算机中最小的存储单位:一个比特位(bit)
1位 = 1比特
字节:1字节 = 1bytes = 8bit
1024bytes = 1kbytes = 1KB
1024KB = 1MB = 1兆
1024MB = 1GB
三、计算机编码的发展历程
(1)最早的编码表是美国发明的ASCII表(美国标准信息交换代码)。它是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言,其最多只能用8位来表示(一个字节),即2**8-1=255,所以ASCII最多只能表示255个符号 (最初是127个字符,后来被拓展到了255个)
(2)但是问题来了,随着计算机的普及,世界各国都有编码的需求,拿中文来举例:ASCII到了中国之后发现,中国最常用的中文都有6000多个完全不够用啊!
那该怎么办?聪明的中国人在原有的扩展位中,扩展出了自己的gbk、gb2312、gb2318字符编码。
可是该如何拓展呢?比如说在ASCII码中的200这个位置,又指定一张单独表, 这张单独表收录了所有中文与字符码的对应关系,这样就完成了拓展。其他国家也是这样设计的!
为了处理汉字,工程师设计了用于简体中文的GB2312和用于繁体中文的big5。
GB2312一共收录了7445个字符,包括6763个汉字和682个其他符号。
GB2312支持的汉字太少了,1995年的汉字拓展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。
2000年,GB18030取代GBK1.0成为国家正式标准,该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要少数民族文字。现在PC平台必须支持GB18030。
从ASCII、GB2312、GBK到GB18030,这些编码是向下兼容的(即后面的高版本兼容前面的低版本),所谓向下兼容是指同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。
(3)显然ASCII码无法将世界上的各种文字和符号全部表示(毕竟只有128个拓展位),所以,就需要新出一种可以代表所有字符和符号的编码,即Unicode。
Unicode(统一码,万国码,单一码,90年代初出现的)是一种在计算机上使用的字符编码。Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,规定所有的字符和符号最少由16位来表示(2个字节),即最多可表示2**16-1=65535个字符。
(4)原本使用ASCII码(一个字节表示一个字符)的美国在使用Unicode(两个字节表示一个字符)之后,电脑存储容量小了一半,比如原先使用ASCII码可以存储100G,在使用Unicode之后只能存储50G,这显然不太合理。于是后面有了Unicode升级版:UTF-8
(5)UTF-8是对Unicode编码的压缩和优化,它不再遵循最少使用2个字节表示一个字符,而是将所有的字符和符号进行分类:ASCII码中的内容用1个字节保存,欧洲的字符用2个字节保存,东亚的字符用3个字节保存(所以今天中文一个字符用3个字节来存储)
四、乱码问题是怎样产生的?
有了上面的介绍后,我们可以归纳一下在编程过程中产生乱码的原因:
(1)字符编码不止一种,编码和解码没遵循同一套字符编码规范
(2)存储方式不同,如不是拿一个字节存储一个字符,则会错位,导致乱码
五、Python编码转换
首先介绍下,Python提供了两个方法用于编码和解码。
编码--encode方法
解码--decode方法(对于没有Python基础的同学来说,后面会讲到Python方法)
编码/解码流程如下:
(1)Python2.x中:
因为Python2.x默认编码是ASCII,所以:
UTF-8转GBK:先decode解码成ASCII,然后再encode编码为GBK;
GBK转UTF-8:先通过decode解码为ASCII,然后再encode编码为UTF-8
编码转换示例:
首先文件头部声明了文件编码为UTF-8,所以需要先decode为ASCII,再将ASCII编码encode为GBK
(2)Python3.x中:
因为Python3.x默认编码是Unicode,所以:
UTF-8转GBK:先decode解码为Unicode,然后再encode编码为GBK
GBK转UTF-8:先decode解码为Unicode,然后再encode编码为UTF-8
编码转换示例: