Title

字符编码

一、字符编码

1、知识储备

1.三大核心硬件

所有软件都是运行在硬件上分,与运行软件相关的三大核心硬件为CPU,内存,硬盘。

  • 软件运行前,软件的代码及其相关数据都是存放在硬盘中

  • 任何软件的启动都是将数据从硬盘中读入内存,然后cpu从内存取出指令并执行

  • 软件运行过程中产生的数据最先都存放去内存中,若需要永久保存软件产生的数据,则需要将数据由内存写入硬盘

2.python解释器执行文件的流程

以py文件为例,

阶段1、启动python解释器,此时就相当于启动了一个文本编辑器

阶段2、python解释器相当于文本编辑器,从硬盘上将test.py的内容读入到内存中

阶段3、python解释器解释执行刚刚读入的内存的内容,开始识别python语法

2、字符编码介绍

1. 什么是字符编码?

人类在与计算机交互时,用的都是人类能读懂的字符,如中文字符、英文字符、日文字符等

而计算机只能识别二进制数,详解如下

#二进制数即由0和1组成的数字,例如010010101010。计算机是基于电工作的,电的特性即高低电平,人类从逻辑层面将高电平对应为数字1,低电平对应为数字0,这直接决定了计算机可以识别的是由0和1组成的数字

毫无疑问,由人类的字符到计算机中的数字,必须经历一个过程,如下

字符——》翻译——》数字

翻译的过程必须参照一个特定的标准,该标准称之为字符编码表,该表上存放的就是字符与数字一一对应的关系。

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

2.字符编码表

英文:ASCII (8个bit位,一个字节)

中文:GBK (2个字节)

日文:shift_JIS

万国码:unicode (2-4个字节)

unicode于1990年开始研发,

1994年正式公布,具备两大特点:

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

#2. 与传统的字符编码的二进制数都有对应关系,详解如下

因此内存中都是unicode,硬盘中有各国不同的编码表

3.编码与解码

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

由内存中的unicode转换成字符,以及由其他编码转换成unicode的过程,都称为解码decode

注意: 在诸多文件类型中,只有文本文件的内存是由字符组成的,因而文本文件的存取也涉及到字符编码的问题

4.utf-8的由来和使用

注意:如果保存到硬盘的是GBK格式二进制,当初用户输入的字符只能是中文或英文,同理如果保存到硬盘的是Shift_JIS格式二进制,当初用户输入的字符只能是日文或英文……如果我们输入的字符中包含多国字符,那么该如何处理?

理论上是可以将内存中unicode格式的二进制直接存放于硬盘中的,但由于unicode固定使用两个字节来存储一个字符,如果多国字符中包含大量的英文字符时,使用unicode格式存放会额外占用一倍空间(英文字符其实只需要用一个字节存放即可),然而空间占用并不是最致命的问题,最致命地是当我们由内存写入硬盘时会额外耗费一倍的时间,所以将内存中的unicode二进制写入硬盘或者基于网络传输时必须将其转换成一种精简的格式,这种格式即utf-8(全称Unicode Transformation Format,即unicode的转换格式)

那为何在内存中不直接使用utf-8呢?

utf-8是不定长的:一个英文字符占1Bytes,一个中文字符占3Bytes,生僻字用更多的Bytes存储

也就意味着如果用户输入的字符是:你y好,在内存中需要先经历计算的过程:“你”应该用3Bytes,“y”应该用1Bytes,“好”应该用3Bytes,然后才能存储,所以内存中如果直接使用utf-8格式去存储字符,耗费的总时间=计算时间+存储时间,而内存中使用定长的unicode格式存储字符,就省去了计算时间,所以内存中使用unicode来存储字符会浪费空间,但是会提升速度,这是一种用空间换时间的方法

5.字符编码的应用

我们学习字符编码就是为了存取字符时不发生乱码问题:

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

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

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

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

总结:保证不乱码核心: 用什么编码存的数据,就用什么编码取

# 1.用户无论输入什么字符,存入内存,unicode都可以兼容
# 2.硬盘中无论是什么编码的文件,读到内存,都可以兼容unicode
# 3.保证存的时候不乱:在由内存写入硬盘时,必须将编码格式设置为支持所输入字符的编码格式
# 4.保证读的时候不乱:在由硬盘读入内存时,必须采用与写入硬盘时相同的编码格式
即:
(内存)unicode二进制字符>>编码(encode)>>(硬盘)utf-8二进制字符
(硬盘)utf-8二进制字符>>解码(decode)>>(内存)unicode二进制字符

注意:python解释器前两个阶段保证读py文件时不乱码,则必须将python解释器读文件时采用的编码方式设置为文件当初写入硬盘时的编码格式,如果没有设置,python解释器则才用默认的编码方式,在python3中默认为utf-8在python2中默认为ASCII,我们可以通过指定文件头来修改默认的编码

  • 文件头:在文件首行写入包含#号在内的以下内容

# coding: 当初文件写入硬盘时采用的编码格式,
例如
# coding:utf-8

解释器会先用默认的编码方式读取文件的首行内容,由于首行是纯英文组成,而任何编码方式都可以识别英文字符。

设置文件头的作用是保证运行python程序的前两个阶段不乱码,经过前两个阶段后py文件的内容都会以unicode格式存放于内存中。

在经历第三个阶段时开始识别python语法,当遇到特定的语法name = '上'(代码本身也都全都是unicode格式存的)时,需要申请内存空间来存储字符串'上',这就又涉及到应该以什么编码存储‘上’的问题了。

在Python3中,字符串类的值都是使用unicode格式来存储

由于Python2的盛行是早于unicode的,因此在Python2中是按照文件头指定的编码来存储字符串类型的值的(如果文件头中没有指定编码,那么解释器会按照它自己默认的编码方式来存储‘上’),所以,这就有可能导致乱码问题

# coding:utf-8 
x = '上'
# x的值为untf-8格式的二进制 print(x) 打印操作是将x的值,即utf-8格式的二进制交给终端,当终端收到后发现并不是unicode(只有unicode才与字符有对应关系),所以终端会执行操作:utf-8二进制---解码-->unicode格式的二进制,解码的过程终端会采用自己默认的编码,而在pycharm的终端默认编码为utf-8、
windows下的cmd终端的默认编码为gbk,所以该打印操作在pycharm中显示正常,而在windows下的cmd中则乱码
# 在windows下的cmd中运行效果如下C:\Users\Administrator>python2
E:\aaa.py

 

posted @ 2019-11-08 00:23  Mr江  阅读(178)  评论(0编辑  收藏  举报