一、什么是字符集、字符编码?

字符集各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、Unicode字符集。计算机要准确的处理各种字符集文字,就需要字符编码,以便计算机能够识别和存储各种文字。常见的字符集有ASCII字符集、GBXXXX字符集、BIG5字符集、通用字符集等。

字符码:指的是字符集中每个字符的数字编号。例如:ASCII字符集用0-127这连续的128个数字分别表示128个字符,“A”的编号就是65。

举个例子:

ASCII字符集

python项目设置字符集 python 字符集_ico

字符编码:将字符集种的字符按照某一规则编码,存储在计算机中。是一套规则,使用该规则能够将自然语言(如字母或中文)的字符编码为指定集合中某一对象(如比特模式、8位组、电脉冲),以便信息在计算机存储和网络传递。常见的字符编码有ASCII字符编码、GBXXXX字符编码、Unicode编码等。

在计算机中,所有信息都是用二进制表示的,每个二进制位(bit)有0和1两种状态。一个字节8个二进制位,8个二进制位可以组合出256种状态。当我们需要把字符“A"存入计算机时,应该如何表示字符“A"呢?存入计算机时,我们可以用01000001二进制来表示"A",即为编码;读取时,将01000001还原成符"A",即为解码

编码:编码的过程是将字符转换成字节流。

解码:解码的过程是将字节流解析成字符。

二、字符编码的发展史

ASCII编码

现代计算机起源于美国,ASCII编码是最早诞生的编码,由美国人定制,一共规定了128个字符。美国人只用英文,所以可以说ASCII编码是专门为表示英文、数字以及英文标点符合的。最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号。这128个符号,只占用了一个字节(8bit)的后7位,最高位统一规定为0位,总共才128个字符编码,一个字节都没用完。于是乎,对最高位为1时也进行了编码,制定了一套非ASCII编码,如ISO-8859-1编码。

ISO-8859-1

这套编码规则由ISO制定。是在ASCII编码基础上又制定了一些标准来扩展ASCII编码的,即00000000(0) ~ 01111111(127)与ASCII编码一样,对10000000(128) ~ 111111111(255)这一段进行了编码。ISO-8859-1编码也是单字节编码,最多能够表示256个字符。Latin1时ISO-8859-1的别名。

GB2312以及其他编码

世界上有多种语言,有中文、韩文、日文等等,每个国家都想使用自己最熟悉的语言来使用计算机。那么,如何在计算机中表示不同的语言呢?很明显,ASCII编码已经无法满足这样的需求了。于是乎,各个国家纷纷定制了自己的编码,比如:GBK2312、Shift_JIS、Euc-kr等等。

1.GBXXXX编码
为了满足国内在计算机中使用汉字的需要,1981 由中国国家标准总局发布了GB2312,又称GB0,这套编码采用双字节进行字符编码。GB2312 编码共收录了6763个汉字,同时他还兼容 ASCII,GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率,不过 GB2312 还是不能100%满足中国汉字的需求,对一些罕见的字和繁体字 ,GB2312 没法处理。后来,就在GB2312的基础上创建了一种叫 GBK 的编码,GBK 不仅收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。

2.BIG5编码
BIG5采用双字节编码,使用两个字节来表示一个字符。高位字节使用了0x81-0xFE,低位字节使用了0x40-0x7E,及0xA1-0xFE。该编码是繁体中文字符集编码标准,共收录13060个中文字,其中有二字为重复编码,即“兀、兀”(A461及C94A)和“嗀、嗀”(DCD1及DDFC)。

3.Shift_JIS
日文编码

4.Euc-kr
韩文编码

Unicode编码

每个国家都有一套自己的编码,那么就不可避免地会有冲突,在多语言混合的文本中,就会出现乱码的情况,如何解决这个问题?Unicode编码应运而生。Unicode编码又被称为统一码、万国码。它为世界上每种语言的每个字符制定了统一且唯一的字符码,以满足跨语言、跨平台进行文本转换、处理的要求。
一开始的Unicode标准UCS-2使用两个字节表示一个字符,但过了不久有人觉得256*256太少了,还是不够用,于是出现了UCS-4标准,使用4个字节表示一个字符,不过用的最多的还是UCS-2。

UTF-8编码

由于使用Unicode编码存储英文时需要2个字节,而原先使用ASCII编码存储英文时只需要1个字节,存储空间大大被浪费了。于是乎,就产生了UTF-8编码,一种可“变长”的编码格式。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,把英文变长为1个字节,汉字变长为3个字节表示,特别生僻的会变成4-6个字节。所以如果是传输或存储大量英文的话,UTF编码格式的优势就会非常明显,能够大大节省空间。

字符

ASCII

Unicode

UTF-8

A

01000001

00000000 01000001

01000001


x

01001110 00101101

11100100 10111000 10101101

说明:
Unicode编码所有字符都是2字节,优点是字符编码快,缺点是占用空间大,是一种空间换时间的编码。而程序运行都需要加载到内存,内存的存取速度应该尽可能保证快。故,内存中使用Unicode编码。

UTF-8编码对不同的字符采用不同长度的字节表示,优点是节省空间,缺点是字符编码慢,因为每次都需要计算出字符需要多长的字节才能准确表示。故,硬盘或者网络传输用UTF-8编码,因为网络I/O延迟或者磁盘I/O延迟远大于UTF-8的转换延迟。

个人小结:
1.为了计算机能够表示英文字符,制定了ASCII编码;
2.为了计算机能够表示中文字符,制定了GB2312编码;
3.为了解决各国语言的冲突问题,制定了Unicode编码;
4.为了提高Unicode的存储和传输性能问题,制定了UTF-8编码,是Unicode的一种实现形式

上述常见编码整理成表格如下:

编码

时间

作用

字节

ASCII

1967年

表示英语及西欧语言

1个字节表示一个字符

GB2312

1980年

中国简体中文字符集,兼容ASCII

2个字节表示一个字符

Unicode

1991年

国际标准组织统一标准字符集,表示多国语言

2个字节表示一个字符

GBK

1995年

GB2312的扩展字符集,支持繁体字,兼容GB2312

2个字节表示一个字符

UTF-8

1992年

不定长编码

1个字节表示英文,3个字节表示中文,4-6个字节表示生僻字

下图,三个文本的内容是一样的(内容大部分为中文),保存时分别选择UTF-8编码、Unicode编码、GBK编码,其中UTF-8编码存储的大小最大,因为UTF-8用3个字节表示中文,占用空间大。而存储英文时使用ASCII编码和UTF-8编码存储的大小应该是一样的。

python项目设置字符集 python 字符集_python项目设置字符集_02


注:

在windows下,保存txt文件时,编码选项有一个ANSI。ANSI并不是某一种特定的字符编码,在不同的系统中,ANSI表示不同的编码。ANSI编码的意思可以理解为“本地编码”,在国内它代表的是GBK,在中国台湾省代表的是Big5,在日本就代表的是JIS。Windows默认为不同的地区选择了默认的编码方式,进入DOS窗口,输入chcp,可以得到操作系统的代码页信息。例如:我的活动代码页为:936,它对于的编码格式为GBK。

python项目设置字符集 python 字符集_ico_03


python项目设置字符集 python 字符集_ico_04

三、不同编码格式和Unicode编码之间的转换

1.计算机中编码格式转换

现在,在计算机内存中统一使用的是Unicode编码。当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

举个例子:

用记事本(编码格式选择UTF-8)编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里;编辑完成后,保存时再把Unicode转换为UTF-8保存到文件。如下图:

python项目设置字符集 python 字符集_开发语言_05

2.python中编码格式转换

在python中,任何非Unicode格式的字符,我们都可以使用decode方式将其解码为Unicode编码的字符,这种转换过程叫“解码”。同理,Unicode格式的字符,也可以通过encode方法将其编码为其他编码格式的字符,这个过程叫“编码”。

python项目设置字符集 python 字符集_python项目设置字符集_06


注:

上述,已经提到过两次编码和解码。第一次提到的编码和解码,是计算机能够表示自然语言时,字符集和计算机二进制码之间的映射过程;第二次提到的编码和解码,是Unicode编码和其它编码格式(GBK编码、ASCII编码)之间进行转换。

参考链接:
https://zhuanlan.zhihu.com/p/25148581 https://zhuanlan.zhihu.com/p/74613584?utm_source=wechat_session