字符编码之理论篇

bit(比特):计算机最新的表示单位,一个0/1

byte(字节):计算机中最小的存储单位。缩写B

计算机内存最小分配单位为字节byte

计算机中数据存储在硬盘是以二进制形式存储。

 GB以后的表示单位:TB/PB/EB/ZB/YB/BB

  • ASCII码:老美编写的,只支持英文字符。分为标准ASCII 码和扩展ASCII 码。一个字符用一个字节byte来表示。因为美国国家语言里的字符数很少,只需要7位(0~127)即可表示,剩下的1位(剩下的1位二进制为0)作为预留。因此使用此范围的编码称为标准ASCII 码也叫基础ASCII码。实现方式:统一形式为0xxxx xxxx

计算机技术到了欧洲,欧洲人发现怎么我们的那么多符号怎么木有啊...刚好老美预留了1位(范围:128~255),实现方式:二进制位1xxx xxxx。完全兼容之前的标准ASCII 码,称之为Latin1(ISO-8859-1)。名字太多了...

同样计算机传入我天朝,一看才1个字节最多表示256个字符,汉语历史悠久且博大精深,据统计汉字接近十万个...一个字节哪里够用。于是产生了第一种汉字编码,把一些常用的汉字及符号包括进去,使用两字节16位,最多可表示两万多个字符,是为GB2312。但是为了能兼容ASCII码,英文字符仍旧是1个字节编码规则的。

规则:ASCII码标准表已足够日常使用,扩展表中的字符使用概率非常低,因此最高二进制位1用不到,而两个字节都是1的概率则更低(也有可能使用扩展表中的字符),因此GBK强行规定:连续两个字节的最高位都是1的话,则代表这是一个汉字字符.

  • GB2312:1980年编写,支持共7445个字符,其中汉字6763个,只支持简体中文
  • GBK:1995年编写,支持21003个汉字,简体和繁体。
  • GBK18030:2000年编写,针对GBK这套编码进一步扩充,包括了中、日、朝鲜语和少数民族语言,有27484个字符。虽然此套编码更全,但是当前很多中文软件默认仍旧使用GBK编码,因为一般情况下足够用了

使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码,所以在中文 windows下要转码成gb2312/gbk,只需要把文本保存为ANSI编码即可。 不同ANSI编码之间互不兼容

其他国家也有自己的编码,但是相互之间都无法兼容,只能自己单独玩耍。为了兼容国际上大部分的编码,国际标准组织ISO编写了Unicode编码(统一码,万国码),规定所有的文字和字符最少使用2B(2B~4B)来进行存储,有32位长度(用于表示字符的位数没有这么多)。

  • Unicode:使用2-4字节进行编码,囊括了世界大部分国家文字和字符,已收录136690个字符。两大作用:
    1. 包含各个国家的字符集(Charset)
    2. 包含各国编码之间的映射关系,方便相互转换  

  通用性是有了,但是带来的问题是原来使用ASCII编码的国家使用了Unicode编码后,原来表示一个字符只需一个byte,而使用了Unicode之后至少使用2B,浪费了存储空间。在计算机系统早些的时候(80x86),RAM(内存or缓存)是几兆甚至KB级别,而硬盘也是兆B级别。网速几kb?编码问题直接导致存储空间与传输量翻倍在当时是无法忍受的(造价昂贵)。

  因此为了解决存储和网络传输的问题,再Unicode的基础上进行了二次编码,做了一些优化,出现了Unicode Transformation Format,缩写UTF:其实就是不改变字符集中各个字符的代码,建立一套新的编码方式,把字符的代码通过这个编码方式映射成传输时的编码,最主要的任务就是在使用Unicode字符集保持通用性的同时节约流量和硬盘空间。主要分为UTF-8,UTF-16,UTF-32三种,数字表示每次传输,传输多少个位。

  • UTF-8:可变长编码,某些字符编码是8位的(例如英语),某些编码是16位的,某些编码是24位(例如中文)。相当于是acsii码仍旧按照原来的编码长度进行编码,欧洲国家使用2B,东亚(中日韩等)字符采用3B。

    规则:用UTF-8在接收时,接到一个编码如果是合法的8位编码,就可以直接把它判定为字符,这就给了Unicode字符集在表示英语时和ASCII一样的效率。如果是不合法的,那继续读一个字节,读的两个字节16位如果是合法的,判别为一个字符,再不行继续读下去,只要传输不出错,终归是能读出的,利用UTF-8的编码规则,这样读取不会出现错判的情况(细节看UTF-8的编码规则)

  • UTF-16:可变长编码,使用2个或者4个字节编码。实际上UTF-16早于UTF-8出现,导致今天Windows系统/JAVA语言等内部编码一直沿用UTF-16  
  • UTF-32:固定长度编码,就是只使用4字节表示所有字符。

UTF这几种编码方案,越是灵活的复杂的编码方案越能节省存储空间,但是相对应的,其效率也是最低的。编码越简单当然效率越高。

Windows中所谓的「Unicode编码」是指「UTF-16le」这种编码方式,因为Windows一直都这样写,也就导致很多人包括很多写书的人沿用了这样的说法。

字符集(Charset):它将抽象字符以数字编码的方式存储在集合中

字符集编码(Character encoding):encoding则是将自然语言的字符和字符集进行配对,是对数据进行存取的一种解决方案。

这里要重点强调一下,ASCII码和Unicode万国码是属于一种字符集(Charset),是编码标准;而诸如GBK/UTF-8等属于字符集编码(Character encoding)

 

 Windows系统默认编码采用GBK,mac、Linux系统默认使用UTF-8(所有操作系统都支持Unicode)

python2默认文件编码为ascii码,解释器加载到内存后的字符串编码也是ascii码。所以代码中要支持中文,文件头必须显示地声明编码为UTF-8/GBK,而此时字符串编码也会同步地变成文件头声明的编码。python2中Unicode的是作为一种单独的数据类型,2.x中type有两种,一种是Unicode,一种就是str(gbk/utf-8/...都是str)

python3默认文件编码是UTF-8,解释器加载到内存后的字符串编码是Unicode。

 问题:

1. GBK编码中英文字符使用几个字节?

2. 为什么Windows终端是GBK,但是能显示Unicode的输出?

中文的编码:

  1. GB2312:
  2. GBK:
  3. GBK18030
  4. BIG5:1985年台湾编写,只支持繁体。

Unicode编码在表示中文的时候,将GBK中表示中文的高位1去掉了。

 

参考:

https://www.zhihu.com/question/52346583/answer/130187864

http://www.mamicode.com/info-detail-1943788.html

http://www.cnblogs.com/alex3714/articles/7550940.html

https://www.cnblogs.com/big-devil/p/7625902.html

=======Python3的执行过程

文件默认编码utf-8,代码文件加载到内存后都是以字符串的形式load,而其字符串编码是Unicode,因此装载到内存会转换成Unicode,

posted @ 2018-04-28 18:39  念宗  阅读(225)  评论(0编辑  收藏  举报