Python的字符编码

一、前言

字符串、以及文本文件的内容都会涉及到字符编码的问题。一旦涉及到字符的存和取,都要考虑字符编码的问题。

字符编码是理论多,而结论少。对于我们日常开发而言,只需要记住结论即可。从而使自己能解决乱码的问题。

二、前置知识

所有的的软件都运行在计算机三大核心硬件中,它们分别是CPU、内存、硬盘

# 1、软件的安装,以及软件的数据、配置都存放在硬盘中(没有运行前)。
# 2、所有的软件运行,都是先从硬盘中将这个软件的数据从硬盘中存入到硬盘。然后是CPU从内存中取出指定并做对应的执行操作
# 3、软件运行的数据,优先存放在内存(内存条)中,而内存中的数据,电脑关机之后,就会自动清空,所以需要永久保存数据,则需要将数据存放在硬盘中。

文本编辑器读取文件内容的流程

# 1、启动一个文本编辑器
# 2、文本编辑器会将打开的文件内容从硬盘读取到内存中。
# 3、CPU会执行文本编辑器发出的指令,从而将文本内容显示到屏幕。

Python解释器处理PY文件的流程

Python 123.py为例

# 1、启动python解释器,此时类似于打开一个文本编辑器
# 2、Python解释器需要从硬盘中读取test.py文件的内容。类似于文本编辑器打开文件
# 3、Python解释器会将读取到test.py的内容进行Python语法解析。

总结

文本编辑器与Python解释器的前两个阶段基本一致。不同的是,文本编辑器只会将文本文件的内容。通过CPU处理之后,输出到屏幕上,根本不在意文件的内容是啥。而Python解释器,则不只是读取文件的内容。它还会解析test.py文件的内容。从而识别文件中对应的python语法

三、字符编码

众所周知,人类和计算即交互的时候,使用的都是人类自己的语言。比如中文、英文、韩文。

而计算机都不认识这些语言。在计算机的世界中,只有0和1。也就是二进制数字。

# 二进制是由0和1组成的,例如:0100101100,而计算机是基于电工作的,电的特性就是高低电频。

毫无疑问,当我们的输入的字符,到计算机那边,它不认识怎么办?那么它就必须经过一个过程,那就是翻译。

比如说,美国人到我们中国旅游。而它不会中文,那么此时如果它想与超市的小姐姐交流,那么就需要一个翻译。去传达(翻译)他说的话。那么计算即也是如此。

Python的字符编码插图

翻译的过程,则必须参照一个标准,那么这个标准就是字符编码表。该表存放的就是字符与二进制的一一对应关系。

字符编码中的编码指的是翻译或者转换的意思,即将人能理解的字符翻译成计算机能识别的数字

编码表的发展史

刚开始,美国人发明了计算机。那么它要能与计算机通信,则就需要一个编码表。所有他就发明了一个字符编码表。即ASCII码表。该表只有字母和数字对应的编码。

# ASCII编码的特点:
# 1、只有字母和数字的一一对应关系。
# 2、一个字母对应一个Byte,1Byte=8bit。8bit最多包含256个数字。可以包含256个字符。足够表示所有的英文字符和数字

而到了后来,我们中国也有了自己对应的字符编码。即GBK。但是GBK编码表,他只定义了中文字符、以及英文字符、数字的一一对应关系。

# GBK编码的特点:
# 只有中文字符、英文字符与数字的一一对应关系
# 1一个字母对应一个字节。一个汉字对应2个字节。
# 补充说明:
     # 1Bytes=8bit,8bit最多包含256个数字,可以对应256个字符,足够表示所有英文字符
     #  2Bytes=16bit,16bit最多包含65536个数字,可以对应65536个字符,足够表示所有中文字符

到了最后,计算机发展到了全世界普遍的地步,那么基本每个国家都有了自己的编码表,而他们编码表。都有一个特征:只有自己国家的语言 + 英文字母 + 数字的一一对应关系。

那么就遇到一个问题,假设韩国人想在自己计算机输入一些中文,那么是输入不了的。因为他们的编码表中没有中文。而GBK的编码表中也没有韩文。所以这种编码表,只限于自己国家的语言+英文+数字。是不能正常显示别国的语言的。

并且,文本我们将数据存入到硬盘中使用到的编码,必须和数据被取出使用的编码一致。不然会乱码。

为了能让计算机使用一个编码表,就能识别到多国的语言。那么Unicode编码就诞生了。

unicode编码的诞生

前面,各国都有自己的编码表。并且指定了某个编码,就不能使用正常显示别国的语言了。

我们这里的指定编码,指定的是将数据写入到硬盘使用到的编码。

为了实现使用一个编码表。识别多国语言,Unicode编码就诞生了,unicode于1990年开始研发,1994年正式公布,具备两大特点:

#1. 存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符

#2. 与传统的字符编码的二进制数都有对应关系,详解如下
Python的字符编码插图1
图源知乎egon老师文章配图

文本编辑器输入任何字符都是最新存在于内存中,是unicode编码的,存放于硬盘中,则可以转换成任意其他编码,只要该编码可以支持相应的字符

# 英文字符可以被ASCII识别
英文字符--->unciode格式的数字--->ASCII格式的数字

# 中文字符、英文字符可以被GBK识别
中文字符、英文字符--->unicode格式的数字--->gbk格式的数字

# 日文字符、英文字符可以被shift-JIS识别
日文字符、英文字符--->unicode格式的数字--->shift-JIS格式的数字

于是就将Unicode编码引用到内存中,而我们写入的时候无论使用什么编码表进行编码。最后都会经过从硬盘将数据取出到内存。而内存使用的Unicode编码,Unicode编码称为万国码,它可以识别很多国的编码。所以这样就不会造成乱码的问题。因为内存中使用的则是万国码。而前期内存使用的则是ASCII码表。

编码和解码

由字符转换到内存中,以及由unicode转换成其他编码的过程,都称为编码,即encode。

由内存中的数据转换为字符,以及由其他编码转换为Unicode编码,都称为解码,即decode

UTF-8的诞生

理论上是可以将内存中unicode格式的二进制直接存放于硬盘中的,但由于unicode固定使用两个字节来存储一个字符,如果多国字符中包含大量的英文字符时,使用unicode格式存放会额外占用一倍空间(英文字符其实只需要用一个字节存放即可)。

为了解决多国能使用自己国家的编码,正确显示出别国的语言外,我们需要一个新的编码。而Unicode字节占用过多。不适合。

所以,UTF-8就应运而生,UTF-8(Unicode Transformation Format)即Unicode的转换格式。

它具有如下特点:

# utf-8是针对Unicode的可变长度字符编码:一个英文字符占1Bytes,一个中文字符占3Bytes,生僻字用更多的Bytes存储

‘’‘
unicode更像是一个过渡版本,我们新开发的软件或文件存入硬盘都采用utf-8格式,等过去几十年,所有老编码的文件都淘汰掉之后,会出现一个令人开心的场景,即硬盘里放的都是utf-8格式,此时unicode便可以退出历史舞台,内存里也改用utf-8,天下重新归于统一
’‘’

四、字符编码的应用

我们学习字符编码,就是为了解决不同编码导致的乱码的问题。

#1、内存中固定使用unicode无论输入任何字符都不会发生乱码

#2、我们能够修改的是存/取硬盘的编码方式,如果编码设置不正确将会出现乱码问题。乱码问题分为两种:存乱了,读乱了

#2.1 存乱了:如果用户输入的内容中包含中文和日文字符,如果单纯以shift_JIS存,日文可以正常写入硬盘,而由于中文字符在shift_jis中没有找到对应关系而导致存乱了

#2.2 读乱了:如果硬盘中的数据是shift_JIS格式存储的,采GBK格式读入内存就读乱了

总结

#1. 保证存的时候不乱:在由内存写入硬盘时,必须将编码格式设置为支持所输入字符的编码格式
#2. 保证取的时候不乱:在由硬盘读入内存时,必须采用与写入硬盘时相同的编码格式

本文作者: x1ong
免责声明:本博客所有文章仅用于学习交流
转载声明:文章为作者原创文章 转载请注明来源
本文链接: https://www.giaoblog.com/python/19396.html
上一篇