字符编码

字符编码

一,了解字符编码

  • 运行程序的三个核心硬件:

cpu,内存,硬盘

  • 计算机基础知识:

应用程序任何操作硬件的请求都需要向操作系统发起系统调用,然后由操作系统去操作硬件。

  • 文本编辑器存取文件:

1:打开编辑器就启动了一个进程在内存当中,所以用编辑器编写的内容也都存放在内存中的。(内存缺点:断电数据丢失)

2:想要永久保存数据,需要点击保存按钮(或Ctrl+S),这时候编辑器会把内存中的数据刷入硬盘。

3:在我们编写一个pu文件时(没有执行),跟编写其他文件没有任何区别,都只是在写一堆的字符而已。

  • Python 解释器执行py文件的原理

1:python 解释器启动时,就相当于启动了一个文本编辑器。

2:python 解释器相当于文本编辑器,去打开 test.py 文件,从硬盘上将 test.py 的文件内容读入到内存中。(pyhon 的解释性,决定了解释器只关心文件内容,不关心文件后缀名)

3:python读取文件内容,识别python语法,执行相应操作。

  • 相同点:python 解释器是解释执行文件内容的,因而python 解释器具备读 py 文件的功能,这一点与文本编辑器一样
  • 不同点:文本编辑器将文件内容读入内存后,是为了显示或者编辑,根本不去理会 python 的语法,而 python 解释器将文件内容读入内存后,可不是为了给你瞅一眼 python 代码写的啥,而是为了执行 python 代码、会识别 python 语法。

二,什么事字符编码

  计算机要想工作必须通电,即用“电”驱使计算机干活,也就是说“电”的特性决定了计算机的特性。电的特性即高低电平(人类从逻辑上将二进制数1对应高电平,二进制数0对应低电平),关于磁盘的磁特性也是同样的道理。结论:计算机只认识数字。

  很明显,我们平时在使用计算机时,用的都是人类能读懂的字符(用高级语言编程的结果也无非是在文件内写了一堆字符),如何能让计算机读懂人类的字符?

必须有一个过程:

# 字符----------->(翻译过程)----------->数字
# 这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准就是字符编码。

两个涉及到字符编码的问题:

1:一个python文件中的内容是由一堆字符串组成的,存取均涉及到字符编码问题。(python文件并未执行,前两个阶段均属于该范畴)

2:python中的数据类型字符串是由一串字符组成的。(python文件执行时,即第三个阶段)

三,字符编码的发展历史与分类(了解)

  计算机由美国人发明,最早的字符编码为ASCII,只规定了英文字母数字和一些特殊字符与数字的对应关系。最多只能用 8 位来表示(一个字节),即:2**8 = 256,所以,ASCII码最多只能表示 256 个符号。

  当然我们编程语言都用英文没问题,ASCII够用,但是在处理数据时,不同的国家有不同的语言,日本人会在自己的程序中加入日文,中国人会加入中文。而要表示中文,单拿一个字节表示一个汉字,是不可能表达完的(连小学生都认识两千多个汉字),解决方法只有一个,就是一个字节用>8位2进制代表,位数越多,代表的变化就多,这样,就可以尽可能多的表达出不通的汉字。

  所以中国人规定了自己的标准gb2312编码,规定了包含中文在内的字符->数字的对应关系。

日本人规定了自己的Shift_JIS编码,韩国人规定了自己的Euc-kr编码。(另外,韩国人说,计算机是他们发明的,要求世界统一用韩国编码,但世界人民没有搭理他们。)

  这时候问题出现了,精通18国语言的小周同学谦虚的用8国语言写了一篇文档,那么这篇文档,按照哪国的标准,都会出现乱码(因为此刻的各种标准都只是规定了自己国家的文字在内的字符跟数字的对应关系,如果单纯采用一种国家的编码格式,那么其余国家语言的文字在解析时就会出现乱码。)

  所以迫切需要一个世界的标准(能包含全世界的语言)于是unicode应运而生(韩国人表示不服,然后没有什么卵用。)

ascii用1个字节(8位二进制)代表一个字符

unicode常用2个字节(16位二进制)代表一个字符,生僻字需要用4个字节

例:

字母x,用ascii表示是十进制的120,二进制0111 1000

汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。

字母x,用unicode表示二进制0000 0000 0111 1000,所以unicode兼容ascii,也兼容万国,是世界的标准

  这时候乱码问题消失了,所有的文档我们都使用但是新问题出现了,如果我们的文档通篇都是英文,你用unicode会比ascii耗费多一倍的空间,在存储和传输上十分的低效。

  本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的 UTF-8 编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:

字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
x 01001110 00101101 11100100 10111000 10101101

从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。

四,字符编码的发展可分为三个阶段(重要)

  • 阶段一:

现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII。

(ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符)

  • 阶段二:

为了满足中文和英文,中国人定制了GBK。

(GBK:2Bytes代表一个中文字符,1Bytes表示一个英文字符。)

阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。

  • 非常重要

  说白了乱码问题的本质就是不统一,如果我们能统一全世界,规定全世界只能使用一种文字符号,然后统一使用一种编码,那么乱码问题将不复存在。
ps:就像当年秦始皇统一中国一样,书同文车同轨,所有的麻烦事全部解决。很明显,上述的假设是不可能成立的。很多地方或老的系统、应用软件仍会采用各种各样的编码,这是历史遗留问题。于是我们必须找出一种解决方案或者说编码方案,需要同时满足:

1:能够兼容万国字符。
2:与全世界所有的字符编码都有映射关系,这样就可以转换成任意国家的字符编码。

  这就是unicode(定长),统一用2Bytes代表一个字符,虽然2**16-1=65535,但unicode却可以存放100w+个字符,因为unicode存放了与其他编码的映射关系,准确地说unicode并不是一种严格意义上的字符编码表,下载pdf来查看unicode的详情:
链接:https://pan.baidu.com/s/1dEV3RYp

  很明显对于通篇都是英文的文本来说,unicode的式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的。)

​  于是产生了UTF-8(可变长,全称Unicode Transformation Format),对英文字符只用1Bytes表示,对中文字符用3Bytes,对其他生僻字用更多的Bytes去存。

  • 总结:

  内存中统一采用unicode,浪费空间来换取可以转换成任意编码(不乱码),硬盘可以采用各种编码,如utf-8,保证存放于硬盘或者基于网络传输的数据量很小,提高传输效率与稳定性。

  基于目前的现状,内存中的编码固定就是unicode,我们唯一可变的就是硬盘的上对应的字符编码。
  此时你可能会觉得,那如果我们以后开发软时统一都用unicode编码,那么不就都统一了吗,关于统一这一点你的思路是没错的,但我们不可会使用unicode编码来编写程序的文件,因为在通篇都是英文的情况下,耗费的空间几乎会多出一倍,这样在软件读入内存或写入磁盘时,都会徒增IO次数,从而降低程序的执行效率。因而我们以后在编写程序的文件时应该统一使用一个更为精准的字符编码utf-8(用1Bytes存英文,3Bytes存中文),再次强调,内存中的编码固定使用unicode。
1:在存入磁盘时,需要将unicode转成一种更为精准的格式,utf-8:全称Unicode Transformation Format,将数据量控制到最精简

2:在读入内存时,需要将utf-8转成unicode
  所以我们需要明确:内存中用unicode是为了兼容万国软件,即便是硬盘中有各国编码编写的软件,unicode也有相对应的映射关系,但在现在的开发中,程序员普遍使用utf-8编码了,估计在将来的某一天等所有老的软件都淘汰掉了情况下,就可以变成:内存utf-8<->硬盘utf-8的形式了。

posted @ 2019-07-05 17:07  光吃葡萄皮  阅读(155)  评论(0编辑  收藏  举报
回顶部