电商培训视频教程,推广网站seo,建筑参考网站,wordpress淘宝客一键原文链接#xff1a;https://www.jianshu.com/p/cde52dfc4a9e 计算机作为人类制造出的最为强大的工具#xff0c;将计算机变得更加强大和好用#xff0c;是近百年来人类科技发展的主旋律和主要动力。
为了充分利用计算机的工具属性#xff0c;让人更简单的理解计算机和更简…原文链接https://www.jianshu.com/p/cde52dfc4a9e 计算机作为人类制造出的最为强大的工具将计算机变得更加强大和好用是近百年来人类科技发展的主旋律和主要动力。
为了充分利用计算机的工具属性让人更简单的理解计算机和更简单的操作计算机是至关重要的于是字符编码成为了计算机发展中非常非常重要的一环。
现在的日常使用中我们很少会再关心编码的问题但实际上在计算机的发展历程中字符编码也经历的几个不同阶段的发展。
BCD 码
本来这篇文章是以 ASCII 码为开端的但是在翻阅文章时偶然看到在计算机真正出现之前最早在打孔卡上面就已经存在使用二进制的编码方式了这种编码方式就是 BCD 码。如今可能只有嵌入式和电子行业的人员还会遇到 BCD 编码。
BCD 编码使用四个二进制位表示一个字符四个二进制位一共可以表示 16 中不同的状态BCD 编码一般会选取其中的 10 种状态来表示 0-9 这十个十进制位然后参与运算。
严格意义上来说BCD码并不属于真正的字符编码因为它至多只能表示 16 种状态并且多数情况下只用来进行数学运算。
ASCII 码
ASCII 码应该是最为程序员所熟知的一种编码它最初由由美国国家标准学会ANSI制定后来被国际标准化组织ISO定为国际标准。
ASCII 码使用一个字节即八个二进制位表示一个字符基础版本的 ASCII 码规定最高位固定为 0剩余的七位分别表示 127 个不同的字符
031及127共33个是控制字符或通信专用字符其余为可显示字符
32126共95个是字符32是空格
4857 为 0 到 9 十个阿拉伯数字 6590 为 26 个大写英文字母 97122 为 26 个小写英文字母 其余为一些标点符号、运算符号等 对于英语国家而言ASCII 码可以覆盖大部分的使用场景但是当计算机开始进入欧洲ASCII 码 127 个码位开始不能满足需求比如法语中带有注音符号的字符 é俄语中的字母 й希伯来语中的 א 等。
ASCII 拓展码
为了解决 ASCII 码对于不同的国家不能满足需求的情况拥有独特语言体系的国家决定利用 ASCII 码闲置的最高位对 ASCII 码进行拓展将 ASCII 码能够表示的字符数量拓展至 256 个。
不同的语言体系开始开始制定其独特的 ASCII 拓展码标准不同的 ASCII 拓展码标准之间 0~127 表示的意义是相同的128~255 表示的意义可能是不同的。比如130 在法语编码中代表了 é在希伯来语编码中却代表了字母 Gimel (ג)在俄语编码中又会代表另一个符号。
这种拓展虽然可以解决一部分的需求但是也引入的新的问题由于不同语言体系各自制定的编码标准不同在一种语言体系进行编码的文件流通到其他语言体系地区时极大的可能会存在不能解码的问题并不利于互相之间的交流和流通。
而且对于不同语言体系中的一些国家即便是 128 个 ASCII 拓展码也远远不能满足实际的需求。比如在我国仅常用的汉字数量就有 6000 多个日本和韩国等国家也拥有自己独特的文字系统。
GB2312
对于文字数量或者字母数量用 ASCII 码或者 ASCII 拓展码远远不能满足需求的国家和地区而言单字节的编码方式显然不再适用。双字节字符集开始出现本文仅以我国编码标准的发展为例进行展开。
为了满足需求我国的科技工作者制定了 GB2312 标准在这个标准中一个汉字适用两个字节进行编码分为高字节和低字节。GB2312 规定这两个字节都要大于 127 以便能够兼容 ASCII 码而不产生混淆其中高字节的范围为 0xA1 ~ 0xF7低字节的范围为 0xA1 ~ 0xFE。使用二进制表示 GB2312 的编码范围为
1010 0001 1010 0001 (0xA1A1)
到
1111 0111 1111 1110 (0xF7FE)理论上GB2312 标准共有 22109 个码位可供使用但在实际的应用过程中为了方便国人理解和使用GB2312 标准采用了分区的方式来对编码进行划分。GB2312 标准一共分为了 94 个区每区含有 94 个位每个区位表示一个汉字/符号。分区定义如下
01 - 09 区为特殊符号 10 - 15 区为用户自定义符号区未编码 16 - 55 区为一级汉字按拼音排序 56 - 87 区为二级汉字按部首/笔画排序 88 - 94 区为用户自定义汉字区未编码 按照分区定义共有 94 * 94 共 8836 个码点可用GB2312 标准中收录了汉字 6763 个和非汉字图形字符 682 个预留了可供用户自定义的码点 1391 个。
GB2312 标准中区位号和二进制之间的转换也十分的简单一个汉字字符的双字节编码的高字节为汉字的区号加上 0xA0低字节则为位号加上 0xA0。
举例说明汉字 ”啊“ 的双字节编码为 0xB0 0xA1区位码为 1601计算方式如下
1010 0000 1010 0000 (0xA0 0xA0)0001 0000 0000 0001 (0x10 0x01) (16 01)1011 0000 1010 0001 (0xB0 0xA1)了解了区位码之后可以更好的理解国标码GB2312 标准中的 GB 就表示国家标准代码简称国标码亦被新加坡采用。国家标准强制标准冠以“GB”。
区位码和国标码的转换规则为把换算成十六进制的区位码加上0x2020就得到国标码国标码加上0x8080就得到常用的双字节十六进制表示。
GBK
随着计算机的不断发展逐渐发现 GB2312 标准中仍旧存在大量没有收录的特殊汉字和少数民族文字。于是在 GB2312-80 标准上拓展出了 GBK 标准。
相较于 GB2312 标准GBK 标准的编码范围进行了拓展变为了 0x8140 ~ 0xFEFE剔除了原本低字节需要小于 127 的限制同时对高字节范围也进行了拓展。
经过拓展后的 GBK 标准共23940个码位收录了21003个汉字并且可以完全向下兼容 GB2312 标准。此后的 GBK 标准还经历过几次的拓展本文不再赘述有兴趣的同学可以自行查阅。
类似于 GB2312 标准和 GBK 标准的这种使用两个字节表示一个字符的编码集通称它们叫做 “DBCS“Double Byte Charecter Set 双字节字符集
自此中文在计算机中有了较为成熟的编码和显示规则。但是不论是 GB2312 标准还是 GBK 标准都属于中国的国家标准而非国际标准相当于在计算机中中国地区拥有了自己独特的方言而对于有着其他方言的国家或者地区互相间的交流仍旧是十分困难的。
此时就需要一个统一的国际化标准来统一不同国家和地区间的字符编码。
Unicode
为了解决不同国家和地区标准字符集不同的问题为每种语言中的每个字符设定统一并且唯一的二进制编码以满足跨语言、跨平台进行文本转换、处理的要求。国际标准化组织ISO于1990年开始研发一种统一编码于1994年正式发布 Unicode 1.0 版本。
Unicode 被称为统一码、万国码或单一码学名是 “Universal Multiple-Octet Coded Character Set”简称为UCS。Unicode用数字 0 ~ 0x10FFFF 来映射这些字符最多可以容纳 1114112 个字符或者说有 1114112 个码位。
Unicode 本意上是制定一个类似于字典的字符集规定了每个符号对应的数字至于这个数字如何存储和传输则没有任何规定。它的想法很简单就是为每个字符规定一个用来表示该字符的数字仅此而已。
既然 Unicode 只规定了字符对应的码点数字 没有规定这个数字如何存储和传输那么对于不同的字符对应的数字如何存储和传输以及计算机应该按照什么样的规则去拆分和理解连续的二进制数据便又衍生出了不同的 UTF 标准。
UFT
上文提及Unicode 本身对于不同的字符对应的数字如何存储和传输并没有任何规定。存储和传输 Unicode 码点的工作由 UTF 标准完成。
简单来讲 UTF 标准规定了在存储和传输过程中需要将一个字节、两个字节还是四个字节解析为一个 Unicode 码点。
为何需要 UTF 有这样一个字符串”a啊“其中包含了三个不同的符号 ”a“ 在 Unicode 中的码点为 U0041 ”啊“ 在 Unicode 中的码点为 U554A ”“ 在 Unicode 中的码点为 U1F600
可以看出”a“ 仅需要一个字节就可以表示”啊“ 需要两个字节表示”“ 则至少需要三个字节。那么如何确定 ”a啊“ 这个字符串的二进制编码以及在连续的二进制编码中如果正确的解读出这三个符号的 Unicode 码点
最简单的方式便是将字符串中码点最大的字符作为标准”a啊“ 中每个字符都用三个字节存储二进制编码便是 ”0x000041 0x00554A 0x01F600“。
但是明显的这种方式会造成极大程度的浪费如果码点最大的字符需要占用 4 个字节而其他字符 1 个字符就可以表示的话这种浪费将是不可接受的。
而如果使用固定的一个字节或者两个字节来表示一个码点对于需要字节数量更多的码点则需要一个规则组合表示而 UTF 就是这个规则的制定者。
本文主要介绍几种常见 UTF 编码格式UTF-8、UTF-16、UTF-32
UTF-8
UTF-8 是一个非常惊艳的编码方式它规定一个字节为一个单位一个码点可能由 1 - 4 个单位来组合表示。由于它可以表示单字节码点完美的实现了对 ASCII 码的向后兼容保证了 Unicode 可以被大众接受。
像 UTF-8 这种一个码点可能由不同字节数表示的编码方式被称为可变长编码。
而对于一个字节不能表示的码点UTF-8 规定使用如下的编码规则
码点 0x0000 - 0x007F 码点二进制 0xxxxxxx UTF-8 编码0xxxxxxx
码点 0x0080 - 0x07FF 码点二进制 00000aaa aabbbbbb UTF-8 编码110aaaaa 10bbbbbb
码点 0x0800 - 0xFFFF 码点二进制 00000000 aaaabbbb bbcccccc UTF-8 编码1110aaaa 10bbbbbb 10cccccc
码点 0x10000 - 0x10FFFF 码点二进制 00000000 000aaabb bbbbcccc ccdddddd UTF-8 编码11110aaa 10bbbbbb 10cccccc 10dddddd UTF-8 的编码解析只需要根据每个字节中第一个 0 之前 1 的数量来确定这个字节和其他字节的组合方式即可。
UTF-16
在了解 UTF-16 编码方式之前可能需要先了解一下另外一个概念 —— “平面”
根据上文我们知道 Unicode 是一本很厚的字典其中定义了世界上所有的字符为了给这些不同的字符进行分类。Unicode 使用了分区定义的方式每个区可以存放 65536 个2^16字符称为一个平面plane。目前一共有 17 个2^5平面。划分如下
0x0000~0xFFFF第0平面基本多文种平面Basic Multilingual Plane, BMP 0x10000~0x1FFFF第1辅助平面多文种补充平面Supplementary Multilingual Plane, SMP 0x20000~0x2FFFF第2辅助平面表意文字补充平面Supplementary Ideographic Plane, SIP 0x30000~0x3FFFF第3辅助平面表意文字第三平面Tertiary Ideographic Plane, TIP 0x40000~0xDFFFF第4-13辅助平面尚未使用 0xE0000~0xEFFFF第14辅助平面特别用途补充平面Supplementary Special-purpose Plane, SSP 0xF0000~0xFFFFF第15辅助平面保留作为私人使用区Private Use Area, PUA 0x100000~0x10FFFF第16辅助平面保留作为私人使用区Private Use Area, PUA
了解了平面的概念后。UTF-16 编码方式就很好理解了它结合了定长和变长两种方式的特点规定基本平面的字符占用 2 个字节辅助平面的字符占用 4 个字节。
但是这里仍旧会存在一个问题当我们遇到两个字节时到底是把这两个字节当作一个字符还是与后面的两个字节一起当作一个字符为了解决这个问题UTF-16 规定了一种巧妙的映射方式。
实际上在基本平面内0xD800 ~ 0xDFFF 中间的码点没有对应任何字符UTF-16 利用了这个空段来映射辅助平面的码点。目前辅助平面的可以容纳的所有码点需要 20 bits 来表示UTF-16 将这 20 bits 拆分为了前 10 bits 和后 10 bits。前 10 bits 被映射到了 0xD800 ~ 0xDBFF后 10 bits 被映射到了 0xDC00 ~ 0xDFFF。
映射完成后前两个字节作为高位后两个字节作为低位四个字节共同表示一个码点计算过程如下
对于小于 0x10000 的码点直接使用码点的十六进制编码 对于 0x10000 ~ 0x10FFFF 之间的码点使用下面的步骤对码点 U 进行编码 1、U‘ U - 0x10000 将码点减去 0x10000得到一个小于 0xFFFFF 的结果这个结果可以用 20 bits 表示 2、U’ xxxx xxxx xxyy yyyy yyyy 将上一步的结果用二进制表示为 20 bits 3、W1 1101 10xx xxxx xxxx W2 1101 11yy yyyy yyyy 将 U‘ 的前 10 bits 映射到 UD800 到 UDBFF 之间得到 W1 将 U‘ 的后 10 bits 映射到 UDC00 到 UDFFF 之间得到 W2 4、W1 W2 W1 和 W2 进行拼接即为最终的编码结果 所以当遇到两个字节的码点在 0xD800 ~ 0xDBFF 之间就可以确定后面两个字节的码点应该在 0xDC00 ~ 0xDFFF 之间而这四个字节必须放在一起进行解读。
UTF-32
由于 Unicode 的码点范围只截止到 0x10FFFF所以 32 bits 足够表示 Unicode 的所有码点因此 UTF-32 也属于定长编码每个码点都使用四个字节进行表示。
作者hackswang 链接https://www.jianshu.com/p/cde52dfc4a9e 来源简书 著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。