JS基础-字符-Unicode编码(上)

首先,我默认你已经熟悉,计算机是使用2进制编码的,这就够了。

现在有一台主机A,需要把 65 和 97 两个10进制数字传输给另外一台主机B,那么A需要把数字转化成2进制传输给B。 物理过程为控制电压,使用高电平(5V)代表1,低电平(0V)代表0,经过传输介质(线缆)传输。 十进制65 转化成二进制为 1000001 十进制97 转化成二进制为 1100001 那么A开始干活,把10000011100001传输出去了。 但问题是,B接收到 10000011100001 时,怎么能知道这是2个10进制的数?我可分割的方式很多啊,比如【10000011100001】,【1000001,1100001】,【1000001,1,100001】... 这就要求所有的主机需要达成一种默契,或者说遵守一种协议,就是要确定解析二进制时基本单位,或基本位数,其实这个数就是我们常说的8bit,也就是8位2进制位一个基本解析单位,不够8位的2进制在左边补0。为了叫着方便,人们还称呼它为,一字节

注意区分字节与字的区别 在16位CPU(8086就是这种CPU)中,一字表示16位(2字节),双字代表32位(4字节)。 在32位CPU中,一字表示32位(4字节),双字表示64位(8字节)。 在64位CPU中,一字表示64位(8字节),双字表示128位(16字节)。

这回B可以根据8bit为一个单位切分,以此知道自己拿到的是2个数字,并且对应的是10进制的 65 和 97

但是为啥要用8位2进制作为一个字节呢? 一字节其实就是 一个文字的节点,顾名思义就是计算机系统用来代表一个文字的基本单位。

在IBM的System/360系统中, IBM研制了自己的8位字符编码,即扩展的BCD交换代码EBCDIC,该编码是早期的BCDIC 6位编码(早期的计算机使用6位编码)的扩展,从IBM穿孔卡片使用的代码演变而来。穿孔卡片可以存放80个文本字符,这种模式由IBM 1928年首先引入并且用了50多年。

IMB,国际商业机器公司或万国商业机器公司。历经美国史上所有的经济危机依然挥然不动,对世界机械工业以及电子工业产生深远影响。在冯**·**诺依曼为美国军方制造出了军用计算机后,就被IMB总裁小沃森聘请为民用大型机(主要是政府部门和大型企业,因为每台造价都高达百万美元以上)计算机制造的顾问,还有一大批强悍的计算机工程师以及麻省理工学院做技术后盾,在20世纪60年代IBM生产出System/360系统时,已经耗费50亿美元,这是什么概念呢,咱们国家1960年的GDP为597.16亿美元。 IBM还参与重要行业标准的制定,总之世界知名的计算机制造商都希望与IBM兼容,但是IMB并不看好PC个人机操作系统这块领域,错失先机,就让微软捷足先登。 总之,IBM的8位字符编码是影响现代计算机采用8位为一字节的重要原因之一。

*IBM的穿孔卡片是怎么来的呢? #####1.雅卡尔织布机

法国发明家约瑟夫·玛丽·雅卡尔在 1799 年发明出了雅卡尔织布机,这种机器能通过判断卡片上是否有孔洞来操纵线团的高低位置。 雅卡尔织布机利用纸带上的孔来对信息进行编码,并作为输入来控制织布机自动工作。 这是最早的自动化生产了吧,对将来发展出其他可编程机器(例如计算机)起了重要作用。

#####2.Herman Hollerith 的制表卡

1880年以前,美国的人口普查都是人工做的。1880的普查完成之后,美国人意识到按照当时的人口增长速度,下一次1890年的普查十年也不可能完成统计,而美国的法律规定必须在十年内完成。Herman Hollerith设计了这种在纸板上打空(punched card)的技术,帮助解决了统计局的难题。1896年他成立了一个公司(TabulatingMachine Company),向其它国家卖他的产品。后来在他老了以后,他把公司卖给了手下的一个主管。最后成了成立IBM的三家公司之一。 美国人口调查局使用着其制表机和制表卡

这回对8位字节由来有了初步认识了吧,其实你我都用过穿孔卡片的直系后代产品,怎么?还没想到?

我就不勾起你痛苦的回忆了(还有我的..),到此打住。

但是,光有主机是不够的,因为人们更习惯于看到跟书本一样的文字符号,所以就需要一个显示器,显示器具有绘制图像的功能,比如说显示器接收到01000001(也就是10进制的65)就绘制一个英文字母A,收到01100001(也就是10进制的97)就绘制一个英文字母a,如图所示

所以,我们可以用一个字节 0000 0000 - 1111 1111表示出256种状态,256种在显示器中也也已对应256个字符,比如ABCD....

我们这两台主机之间这么随意用二进制代表文字没什么问题,但当其他数以万计的主机和我们在一起通信时,就必须要有一个统一的标准了。 各玩各的,没法交流

幸运的是,早已经有了这样一个标准,即美国信息交换标准代码,简写为ASCII码。它于1967年正式公布,此后一直是计算机工业界最为重要的标准。可以肯定的是,无论什么时候处理文本,总会以某种方式涉及到ASCII码。 ASCII码表

但其实可以发现,ASCII码采用的是7位编码,及000 0000 - 111 1111,0-127, 共128种状态一一对应字符。这就奇怪了,7位够用了啊,为啥用8位? 别急,我们还要顺着之前的IMB的情节把故事讲完。

在IBM的EBCDIC中的许多8位码没有定义,建议采用ASCII码的7位编码是合理的。当ASCII码研制出来的时候,存储器非常昂贵,于是一些人感到ASCII码应该用6位码并且采用转义字符来区分大小写用以节约存储器。这种观点没有被接受,相反,人们认为ASCII码应该是8位编码,因为即使在当时人们也普遍认为计算机应该是按8位存储,而不是7位。当然, 8位字节现在是标准的。因此,尽管ASCII码在技术上是7位编码,但它普遍是接8位来存储的。《摘自编码奥秘》

其实8位编码对于ASCII编码多出来的一位还有一个用处,有些机器是有奇偶校验功能的。 比如偶校验, 0000 0111,由于只有3个1,就是奇数,这时需要在最高位写1,变成1000 0111。 如果是这样:0010 0111,就保持不变。 总之一字节中1的个数必须是偶数。接收方如果发现一字节中1的个数变成了奇数,就可以断定这个字节存在错误,在数据传输过程中,有些位数是可能丢失的,这并不奇怪,奇偶校验可以预防错误数据。

有序的排列有利于字母的大小写转换 65 | 32 = 97 大写转小写 97 | ~32 = 65 小写转大写

65 ^ 32 = 97 大写转小写 97 ^ 32 = 65 小写转大写

看来这其中的历史缘由错综复杂,不过好在8位为1字节的标准是确定下来了。

在当时,只有美国有普及计算机的能力,所以压根就没考虑其他国家的文字编码问题,美国生产的计算机只能能显示英文,你必须会英文才能使用,真是太操蛋了。(咱们国家从1983年起,把英语成绩计入高考总分不是因为这吧?)

等到同样使用拉丁字母语系的欧洲人也开始普及计算机的时候,发现ASCII码上没有自己的声调字母(ā á ǎ à ō ó ǒ ò...),欧洲人就想啊,本是同根生,相煎何太急啊,不过他们的声调字母也不是很多,数巴数巴也没超过128(一字节能表示256中字符,减去ASCII的128个,还剩128个),于是法国、德国.....也都自己搞了一套编码,在ASCII编码的基础上加上了自己的声调字母,叫什么EASCII编码字符集。但是ISO国际标准化组织看不下去了,老子总部就在欧洲,真是拿着熊猫不当人啊,于是出台了一套ISO-8859系列标准,特供欧洲。 绿色代表控制字符,在 ISO/IEC 6429 中定义,其实也没改变ASCII原本位置的控制符,只是增添了一些,这个不重要。

但是当我们也开始使用计算机的时候,发现这一个字节根本不够用,因为我们常用的汉字就2500多个,你这余下的128个空余字符位打发要饭的呢?于是咱们中国人心一横,去你大爷的,老子用2个字节代表一个文字,但还不能太任性,需要兼容一下ASCII,为啥呢?首先我们需要获取国际的信息,其次,当时哪些计算机配套的办公电子设备的操作指令都是根据ASCII的控制字符造的,因为那时的咱们这些都主要依赖进口的。所以我们根据 ISO 2022 (根据ECMA-35而来,眼熟吧,ECMA-262知道是啥吧,ECMAISO真算的上是好基友,一辈子)制定了我们自己的字符集编码 GB2312

GB 2312 标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。 GB 2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。但对于人名、古汉语等方面出现的罕用字和繁体字,GB 2312不能处理,因此后来GBK及GB 18030汉字字符集相继出现以解决这些问题。

GB2312具体是怎么编码的?

首先,GB2312使用1字节或2字节动态编码,也就是说,编码一个字符,有可能是8位,也可能是16位。

使用8位编码的字符,就是ASCII编码里的字符,一丁点改动都没有。 使用16位编码的字符,就是我们自己的了,如下图 GB2312部分编码

注意:每个区第一位和最后一位不能设置字符,因为这里由ISO规定为一个是空格,一个是控制符,与ASCII码对应,所以每个区只能使用94个字符位,

**0109区(682个):**特殊符号、数字、英文字符、制表符等,包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母等在内的682个全角字符; **1015区:**空区,留待扩展;在附录3,第10区推荐作为 GB 1988–80 中的94个图形字符区域(即第3区字符之半形版本)。 **1655区(3755个):**常用汉字(也称一级汉字),按拼音排序; **5687区(3008个):**非常用汉字(也称二级汉字),按部首/笔画排序; **88~94区:**空区,留待扩展。

GB2312全表链接,下载完直接浏览器打开。 链接:https://pan.baidu.com/s/1dKyyHxNK8Np077dZ6Ifvhg 提取码:xbct

他一共分成了 94个区(想看全图先下载),每个区能放94个字符,所以理论上可以表示94 * 94 = 8836 个字符,但是有的区在GB2312中暂时没用,在GBK用上了。 我们以为例说明,

1.它的码点为 第04区,第0行(以0开始),第 2个(以0开始)。所以它的编号为04 02 注意,是16进制的。 2.把 04 + A0 = A4, 把02 + A0 = A2,所以, 它的码点为 A4 A2

加个A0是什么鬼?ISO 2022标准就是这么规定的

在1个7比特的字符编码空间,图形字符总计为94个(由于空格符占用了0x20码位、Del符占用了0x7F码位)或者96个。对于双字节的7比特编码空间,图形字符可以有94 x 94即8836个。对于三字节的7比特编码空间,图形字符可以有94×94×94即830584个(虽然没有三字节字符集向ISO登记)。

  1. 0x00 - 0x1f(0-31) 保留给 C0 控制块
  2. 0x20 - 0x7f(32-127) 保留给 G0 图形块(包括空格和 DEL)
  3. 0x80 - 0x9f(128-159) 分配给 C1 控制块
  4. 0xa0 - 0xff(160-255) 分配给 G1、G2 和 G3 图形块,用转义序列切换

总之就是,ISO用掉的部分,你不能用,分配给你的区域就是 0xA0 - 0xFF,你不按我的来就是看不起我,那看得起我的人生产的设备你就用着就爽不了。就是这么霸道。

那么GB2312的16进制码点怎么转化成2进制呢? 兼容的一个字节的部分,也就是兼容ASCII的部分,还是保持原样, 比如A,还是01000001

特别注意,不要把GB2312的03区和ASCII码混淆,虽然他们很像,但不是一个东西,03区也是2字节编码的,至于为什么这样设计,有的说可能是03区的是全角的英文字符。

GB2312添加的部分使用2字节,比如,它的码点为A4 A2, 转化为2进制,为10100100 10100010

#####如果是一字节或两字节动态编码,计算机如何区分呢?

从上可以发现,两个字节为一个字符的都是1开头,一个字节为一个字符的都是0开头,这样计算机在解码的时候就知道,遇到两个相邻的1开头的字节时,他们两个代表一个字符,遇到0开头的时候,知道他是一字节代表一个字符。

动态编码是编码世界里重要的理念,以后会多次涉及。

那么,“你也说聊斋,我也说聊斋”。此时世界开启了一场“聊斋”大战,所有拥有独立文字的国家纷纷制定属于自己的字符集编码,真是一片混乱。这个是时候,ISO组织以“带头大哥”的身份站了出来!成为了一个真男人!

他们整了一个ISO/IEC 10646,准备把全世界的字符都整理进去,并且之后几年,另一个组织也开始搞同样的事情,就是由Xerox、Apple等软件制造商组成的统一码联盟,称Unicode。那么ISO和Unicode孽缘就此开始了。