写点什么

计算机编码简析 (1)

用户头像
Android架构
关注
发布于: 5 小时前

1.2 编解码解决什么?




既然编码的结果是产生二进制的数据,所以编解码显然是人类与计算机的交流方式。再任何的有关软件和硬件的相互操作中,都需要使用编码,对于 Android、Java 来说,就是 I/O 操作了,比如:


  1. 数据持久化

  2. 网络数据传输


2. 几种编码方式


===========================================================================


2.1 ASCII 及扩展集




在计算机早期时,并没有一套统一的编码算法,每个人都能自己定义编解码,而大家如果要想互相通信而不造成混乱,那么大家就必须使用相同的编码规则,于是美国有关的标准化组织就出台了 ASCII 编码,统一规定了常用符号用哪些二进制数来表示。

2.1.1 ACII 码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码) 是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最早也是最通用的信息交换标准。


ASCII 第一次以规范标准的类型发表是在 1967 年,最后一次更新则是在 1986 年,共定义了 128 个字符。


下表为最终规范的 ASCII 码:



ASCII 是一种无符号单字节 的编码方案,基于文本数据,所以它的取值范围是 0~127(10)


其中 第 0-31、127 个是不可见字符(即控制字符),第 32-126 是常用的可见字符

2.1.2 ISO 字符集

由于标准 ASCII 字符集字符数目有限,无法满足要求。为此, ISO(International Organization for Standardization,国际标准化组织) 又制定了 一系列标准,它规定了在保持兼容的前提下将 ASCII 字符集扩充为 8 位代码的统一方法(即双字节编码)。 也就是说可以使用的字符从原来的 128 个扩充到了 256 个,其中的前 128 个是 ASCII 码,即 ISO-8859


但是在当时,由于每个国家和地区,都有自己的语言和输入系统,所以 256 个字符难以统一各个区域,所以 ISO 为每个区域规定了他们自己的标准,例如:


  • ISO-8859-1:又称“西欧语言”;可使用的语言例如:荷兰语、西班牙语、德语、意大利语等。

  • ISO-8859-2:又称“中欧语言”;可使用的语言例如:克罗地亚语、捷克语、匈牙利语、波兰语等。

  • ISO-8859-3:又称“南欧语言”;可使用的语言例如:世界语、马耳他语等。

  • ISO-8859-4:又称“南欧语言”;可使用的语言例如:爱沙尼亚语、格陵兰语、拉脱维亚语等。


这也说明了 ISO-8859 不是一个字符集方案,而是一个系列的字符集方案,同样的码位可以映射不同的字符集。


2.2 国标




作为中国人,我们在使用计算机的时候,自然的会使用到汉字,而上述提供的 ASCII 和 ISO 中,都不支持汉字的字符,所以国内也搞了一套方案。


汉字有上万字,但是常用的只有几千个,最最常用的也就 3000 个左右。

2.2.1 GB 2312

GB 2312 标准共收录 6763 个汉字,其中一级汉字 3755 个,二级汉字 3008 个;同时,GB 2312 收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的 682 个全角字符。


每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”(也称“区字节)”,第二个字节称为“低位字节”(也称“位字节”)。


区字节含义:


GB 2312 中对所收汉字进行了“分区”处理,每区含有 94 个汉字/符号。这种表示方式也称为区位码。


  • 01-09 区为特殊符号

  • 16-55 区为一级汉字,按拼音排序

  • 56-87 区为二级汉字,按部首/笔画排序

  • 10-15 区及 88-94 区则未有编码。


举例来说,“啊”字是 GB2312 之中的第一个汉字,它的区位码就是 1601。


汉字区的内码范围高字节从 B0-F7(176-247),低字节从 A1-FE(161-254),占用的码位是 72*94=6768,其中有 5 个空位是 D7FA-D7FE。


例如“啊”字在大多数程序中,会以两个字节,0xB0(第一个字节) 0xA1(第二个字节)储存。区位码=区字节+位字节(与区位码对比:0xB0=0xA0+16,0xA1=0xA0+1)。

2.2.2 GBK

尽管 GB2312 收录了总共 6000 多个汉字,但是这仍然比较少,还不能覆盖到绝大多数场景的需求。


在 1995 年,国家出台了 GBK(《汉字内码扩展规范》国标扩展的英文简称)规范,GBK1.0 收录了 21886 个汉字,是 GB2312 的 3 倍。


GBK 向下与 GB 2312 编码兼容,向上支持 ISO-10646.1国际标准,在历史的发展中,它是一个对 GB2312 承上启下的产物。


GBK 编码,是在 GB2312-80 标准基础上的内码扩展规范,使用了双字节编码方案,共 23940 个码位,共收录了 21003 个汉字,完全兼容 GB2312 标准。他还能支持日文假名、繁体中文等字符。


GBK 也是使用 区字节+位字节的方式存储,而其高字节的从 81-FE,低字节从 40-FE,总共有 24066 个位置。

2.2.3 GB18030

GB18030 是 2000 年国家出台的取代 GBK1.0 的国标方案,用于补充 GBK 的字符,所以它是兼容 GBK 和 GB2312


它有两个大的历史版本:


  • GB18030-2000


2000 年的版本,收录 27533 个汉字。标准兼容 Unicode 3.0 中日韩统一表意文字


  • GB18030-2005


2005 年更新,收录 70244 个汉字,更新至


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


Unicode 3.1 中日韩统一表意文字,并收录了少数名族的文字如朝鲜族、蒙古文、藏文、维吾尔文、彝文等。


GB18030 的编码采用单字节、双字节和 4 字节方案。其中单字节、双字节和 GBK 是完全兼容的。


下面是 GB18030 的解析规则:


  • 单字节


使用 0×00(0)至 0×7F(127)码位,与 ASCII 码对应


  • 双字节


首字节码位从 0×81(129)至 0×FE(254),尾字节码位分别是 0×40(64)至 0×7E(126)和 0×80(128)至 0×FE(254)。和 GBK 一样(带扩展)。


  • 四字节


四字节部分采用 GB/T 11383 未采用的 0×30(48)到 0×39(57)作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为 0×81308130(2,167,439,664)到 0×FE39FE39(4,265,213,497)。其中第一、三个字节编码码位均为 0×81(129)至 0×FE(254),第二、四个字节编码码位均为 0×30(48)至 0×39(57)。


  • 判断规则


从头开始读取字节,字节范围是 0~127 则是一个字节表示一个字符。


从头开始读取字节,首字节范围是 129-254,判断第二位字节;第二位字节如果是 48~57 则是四个字节表示一个字符,反之是两个字节表示一个字符。


2.3 Big5




Big5(又称大五码或五大码),它的出现时间是 90 年代,是使用繁体中文(正体中文)社区中最常用的电脑汉字字符集标准,共收录 13,060 个汉字。是由台湾那边创建的,主要使用的地区是台湾、香港、澳门这些使用繁体的区域。但它本身不是国家/地区的官方标准,只是行业标准。


Big5 码是一套双字节字符集,使用了双八码存储方法,以两个字节来安放一个字。第一个字节称为“高位字节”,第二个字节称为“低位字节”。“高位字节”使用了 0x81-0xFE,“低位字节”使用了 0x40-0x7E,及 0xA1-0xFE。百度到的分区如下:



2.4 Unicode




Unicode 是由 ISO 组织来设计的,它又称万国码、统一码,第一版公布于 1994 年,设计原因是统一所有的 ASCII 扩展、ISO 字符集、各个国家的字符系统。


所以它和 GB 系列是同期的,在 90 年代,GB 系列和 Unicode 应该是在争字符集的 no.1 的,在 21 世纪之后,Unicode 更受世界各地所接受,因为它功能太过强大了,比如除了支持欧美、亚洲的字符集,还支持中亚的从右到左的书写体系,所以后期它成为了字符集的第一了。

2.4.1 Unicode

Unicode 全称为 Universal Multiple-Octet Coded Character Set,简称 USC,俗称才是 Unicode。


Unicode 和 GB、大五码不一样,它没有规定字符如何在计算机中存储,它为每种语言中的每个字符设定了统一并且唯一的二进制编码。 也就是说它是抽象,而不是实现。


上面提到,Unicode 没有规定字符对应的二进制码如何存储。以汉字“汉”为例,它的 Unicode 码点是 0xE6B189,对应的二进制数是 (111001101011000110001001),二进制数有 18 位,这也就说明了它至少需要 3 个字节来表示。可以想象,在 Unicode 字典中往后的字符可能就需要 3 个字节或者 4 个字节,甚至更多字节来表示了。


这就导致了一些问题,


  • 计算机怎么知道你这个 2 个字节表示的是一个字符,而不是分别表示两个字符呢?


这里我们可能会想到,那就取个最大的,假如 Unicode 中最大的字符用 4 字节就可以表示了,那么我们就将所有的字符都用 4 个字节来表示,不够的就往前面补 0。


  • 这样确实可以解决编码问题,但是却造成了空间的极大浪费,如果是一个英文文档,那文件大小就大出了 3 倍,这显然是无法接受的。


于是,为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16 两种当前比较流行的编码方式诞生了。当然还有一个 UTF-32 的编码方式,也就是上述那种定长编码,字符统一使用 4 个字节,虽然看似方便,但是却不如另外两种编码方式使用广泛。

2.4.2 UTF-16

UTF-16 是 Unicode 的一个分支,全称 Unicode Transfer Format。16 的意思是因为最早是使用两个字节(16byte)来表示所有的字符,但是由于设计师没有考虑字符的数量庞大, 两个字节不足以表示所有字符,所以后面设计成 2 或 4 个字节表示一个字符


综上所述,UTF-16 是一种变长编码,它由 2 字节或 4 字节来表示。来看看它的编码范围:


| 字节数量 | 16 进制编码范围 | UTF-16(二进制) | 10 进制编码范围 |


| --- | --- | --- | --- |


| 2 | U+0000 - U+FFFF | xxxx xxxx xxxx xxxx - yyyy yyyy yyyy yyyy | 0~65535 |


| 4 | U+10000 - U+10FFFF | 1101 10yy yyyy yyyy - 1101 11xx xxxx xxxx | 65536-1114111 |


UTF-16 大部分的字符都是 2 字节,所以它能节省不少带宽,不过它不能兼容 ASCII 码。

2.4.3 UTF-8

UTF-8 也是 Unicode 的一个分支,它也是一种变长编码,使用 1~4 个字节来表示一个字符,因为 1 个字节的关系,所以它比起 UTF-16 可以兼容 ASCII 码。


它的判断规则为:


  • 对于 UTF-8 编码中的任意字节 X,如果 X 的第一位为 0,则 X 独立的表示一个字符(ASCII 码)

  • 如果 X 的第一位为 1,第二位为 0,则 X 为一个多字节字符中的后续字节(非第一字节)

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
计算机编码简析(1)