Unicode 简介、发展历程与编码方式

原文链接: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 个不同的字符:

0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符)

32~126(共95个)是字符(32是空格)

48~57 为 0 到 9 十个阿拉伯数字
65~90 为 26 个大写英文字母
97~122 为 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 中的码点为 U+0041
    ”啊“ 在 Unicode 中的码点为 U+554A
    ”😀“ 在 Unicode 中的码点为 U+1F600

可以看出,”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 映射到 U+D800 到 U+DBFF 之间得到 W1
   将 U‘ 的后 10 bits 映射到 U+DC00 到 U+DFFF 之间得到 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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/880511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机的水位检测系统仿真

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机,DHT11温湿度采集温湿度,滑动变阻器连接ADC0832数模转换器模拟水位传感器检测水位,通过LCD1602显示信息,然后在程序里设置好是否…

【文件增量备份系统】MySQL百万量级数据量分页查询性能优化

🎯 导读:本文针对大数据量下的分页查询性能问题进行了深入探讨与优化,最初查询耗时长达12秒,通过避免全表计数及利用缓存保存总数的方式显著提升了浅分页查询速度。面对深分页时依然存在的延迟,采用先查询倒数第N条记录…

时间序列LSTM实现

这个代码参考了时间序列预测模型实战案例(三)(LSTM)(Python)(深度学习)时间序列预测(包括运行代码以及代码讲解)_lstm预测模型-CSDN博客 结合我之前所学的lstm-seq2seq里所学习到的知识对其进行预测 import time import numpy as np import pandas as pd import torch import…

Meta Sapiens 人体AI模型

Meta 一直是开发图像和视频模型的领导者,现在他们又增加了一个新东西:Meta Sapiens。和Homo sapiens一样,这个模型也是关于人类的。它旨在执行与人类相关的任务,例如理解身体姿势、识别身体部位、预测深度,甚至确定皮肤…

算法课习题汇总(3)

循环日程表 设有N个选手进行循环比赛,其中N2M,要求每名选手要与其他N−1名选手都赛一次,每名选手每天比赛一次,循环赛共进行N−1天,要求每天没有选手轮空。 例如4个人进行比赛: 思路: 把表格…

Spring MVC 基本配置步骤 总结

1.简介 本文记录Spring MVC基本项目拉起配置步骤。 2.步骤 在pom.xml中导入依赖&#xff1a; <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.0.6</version><scope>…

通过WebTopo在ARMxy边缘计算网关上实现系统集成

随着工业互联网技术的发展&#xff0c;边缘计算成为了连接物理世界与数字世界的桥梁&#xff0c;其重要性日益凸显。边缘计算网关作为数据采集、处理与传输的核心设备&#xff0c;在智能制造、智慧城市等领域发挥着关键作用。 1. BL340系列概述 BL340系列是基于全志科技T507-…

MATLAB仿真实现图像去噪

摘要 数字图像处理是一门新兴技术&#xff0c;随着计算机硬件的发展&#xff0c;其处理能力的不断增强&#xff0c;数字图像的实时处理已经成为可能。由于数字图像处理的各种算法的出现&#xff0c;图像处理学科在飞速发展的同时逐渐向其他学科交叉渗透。数字图像处理是一种通过…

【目标检测】隐翅虫数据集386张VOC+YOLO

隐翅虫数据集&#xff1a;图片来自网页爬虫&#xff0c;删除重复项后整理标注而成 数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;386 标注…

电子电路的基础知识

电子电路是现代电子技术的基础&#xff0c;由电子元件&#xff08;如电阻、电容、电感、二极管、晶体管等&#xff09;和无线电元件通过一定方式连接而成的电路系统。 以下是对电子电路的详细概述&#xff1a; 一、定义与分类 定义&#xff1a;电子电路是指由电子器件和有关无…

240925-GAN生成对抗网络

GAN生成对抗网络 GAN&#xff0c;顾名思义&#xff0c;gan……咳咳&#xff0c;就是干仗嘛&#xff08;听子豪兄的课讲说这个名字还真的源于中文这个字&#xff09;&#xff0c;对应的就有两方&#xff0c;放在这里就是有两个网络互相对抗互相学习。类比武林高手切磋&#xff…

dev containers plugins for vscode构建虚拟开发环境

0. 需求说明 自用笔记本构建一套开发环境&#xff0c;用docker 虚拟插件 dev containers,实现开发环境的构建&#xff0c;我想构建一套LLMs的环境&#xff0c;由于环境配置太多&#xff0c;不想污染本地环境&#xff0c;所以选择隔离技术 1. 环境准备 vscodedocker 2. 步骤…

韦东山FreeRTOS笔记

介绍 这篇文章是我学习FreeRTOS的笔记 学的是哔哩哔哩韦东山老师的课程 在学习FreeRTOS之前已经学习过江协的标准库和一丢丢的超子说物联网的HAL了。他们讲的都很不错 正在更新&#xff0c; 大家可以在我的Gitee仓库中下载笔记源文件、项目资料等 笔记源文件可以在Notion…

idea.vmoptions 最佳配置

1. 推荐的 idea64.exe.vmoptions 配置&#xff1a; -Xms1024m -Xmx4096m -XX:ReservedCodeCacheSize512m -XX:UseG1GC -XX:SoftRefLRUPolicyMSPerMB50 -XX:CICompilerCount4 -XX:HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Dsun.io.useCanonCachesfalse -Dj…

微服务JSR303解析部署使用全流程

目录 1、什么是JSR303校验 2、小试牛刀 【2.1】添加依赖 【2.2】添加application.yml配置文件修改端口 【2.3】创建实体类User 【2.4】创建控制器 【2.5】创建启动类 【注意】不必创建前端页面 3、规范返回值格式&#xff1a; 3.1添加ResultCode工具类 3.2添加Resul…

NASA数据集:ATLAS/ICESat-2 L3B 南极和北极网格陆地冰高,第 3 版

目录 简介 摘要 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ATLAS/ICESat-2 L3B Gridded Antarctic and Arctic Land Ice Height V003 简介 ATLAS/ICESat-2 L3B 南极和北极网格陆地冰高&#xff0c;第 3 版 ATL14 和 ATL15 将 ATLAS/ICESat-2 L3B 年度陆地冰…

【蓝桥杯省赛真题55】Scratch找不同游戏 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解

scratch找不同游戏 第十五届青少年蓝桥杯scratch编程选拔赛真题解析 PS&#xff1a;其实这题在选拔赛里面就出现过类似的题目&#xff0c;只是难度提升了一点&#xff0c;具体可以见【蓝桥杯选拔赛真题84】Scratch找不同游戏 第十五届蓝桥杯scratch图形化编程 少儿编程创意编…

java日志门面之JCL和SLF4J

文章目录 前言一、JCL1、JCL简介2、快速入门3、 JCL原理 二、SLF4J1、SLF4J简介2、快速入门2.1、输出动态信息2.2、异常信息的处理 3、绑定日志的实现3.1、slf4j实现slf4j-simple和logback3.2、slf4j绑定适配器实现log4j3.2、Slf4j注解 4、桥接旧的日志框架4.1、log4j日志重构为…

通过队列实现栈

请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。int pop() 移除并返回栈顶元素。int to…

Android源码管理

文章目录 需求及场景需求困难疑惑点 源码管理方式及过程基本仓库管理方式 常用源码git 命令git init添加.gitignoregit add allgit add 文件名称git commit -a -m "提交内容说明"git statusgit loggit reset --hardgit clean -fd实际场景&#xff0c;从一个项目切换到…