【转】刨根究底字符编码之十——Unicode字符集的字符编码方式

一、字符编码方式CEF的选择

1.

由于Unicode字符集非常大(并且作为开放字符集还在不断扩展之中),有些字符的编号(即码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用两个或两个以上字节。

比如,汉字“严”的Unicode编号以十六进制数表示为4E25,转换成二进制数有15位(100 1110 0010 0101),对“严”这个字符的编号进行编码的话,至少需要2个字节。表示其他更大编号的字符,可能需要3个字节或者4个字节,甚至更多。

2.

这带来两个问题:

一是,如何才能区别Unicode字符和ASCII字符的编码?计算机怎么知道三个字节表示的是一个字符,而不是分别表示三个字符呢?

二是,我们知道,英文字母只用一个字节来编码就够了,而如果Unicode统一硬性规定,每个字符都用两个、三个或四个字节来编码,那么每个英文字母编码的前面都必然有一个、两个到三个字节全是0,这对于存储和传输来说是极大的浪费。

这就涉及到了字符编码方式CEF的选择问题。Unicode字符的编码方式目前最常用的是这三种:UTF-8、UTF-16、UTF-32。在具体介绍这些编码方式之前,需要再次深入了解两个概念——码点(Code Point)与码元(Code Unit)。

 

二、码点

1.

一个字符集一般可以用一张或多张由多个行和多个列所构成的二维表来表示。

二维表中行与列相交的点,称之为码点(Code Point代码点),也称之为码位(Code position代码位);每个码点分配一个唯一的编号,称之为码点值或码点编号,除开某些特殊区域(比如代理区、专用区)的非字符码点和保留码点,每个码点唯一对应于一个字符。

因此,除开非字符码点和保留码点,码点值(即码点编号)通常来说就是其所对应的字符的编号,所以码点值有时也可以直接称之为字符编号,虽然不够准确,但更为直接。

2.

字符集中所有码点数量的总和,称之为编号空间(Code Space,又被称之为代码空间、编码空间、码点空间、码空间)。

码点值最初用两个字节的十六进制数字表示,比如字母A的Unicode码点值为0041,常写作U+0041,这种形式称为Unicode码点名称,不严格地来讲,也可称之Unicode字符名称(因为存在着非字符码点和保留码点,并非每个码点都分配了字符,所以这种称呼不够准确,不过目前更为普遍)。

3.

后来随着Unicode字符集的不断增补扩大(比如现在的Unicode字符集至少需要21位才能全部表示),码点值也扩展为用三个字节或以上的十六进制数字表示。

例如,ASCII字符集用0~127这连续的128个数字编号分别表示128个字符。GBK字符集使用区位码的方式为每个字符编号,首先定义一个94×94的矩阵,行称为“区”,列称为“位”,然后将所有国标汉字放入矩阵当中,这样每个汉字就可以用唯一的“区位”码来标识了。例如“中”字被放到54区第48位,因此其区位码(字符编号)就是5448。

而目前Unicode标准中,将字符按照一定的类别划分到0~16这17个平面(Plane层面)中,每个平面中拥有2^16 = 65536个码点,因此,目前Unicode字符集所拥有的码点总数,也就是Unicode的编号空间为17*65536=1114112。

注意,网络上的很多文章中,代码点、码点、码点值、码值、代码位、码位、字符码、Unicode码、字符编号、字符编码、编码方案、编码方式、编码格式等等概念经常互相代替混用,让人困惑。

(笨笨阿林原创文章,转载请注明出处)

 

三、码元

1.

在计算机存储和网络传输时,码点值(即字符编号)被映射到一个或多个码元(Code Unit代码单元、编码单元)

码元可理解为字符编码方式CEF(Character Encoding Form)对码点值进行编码处理时作为一个整体来看待的最小基本单元(或称为最小基本单位)

2.

为什么非要引入“码元”这个概念?或者说,为什么非要强调“码元”这个概念?

码元某种程度上可认为对应于高级语言中的基本数据类型。而高级语言层面的基本数据类型,若要更深入一步地来讲,实质上对应于机器硬件层面(如汇编语言层面)的数据类型byte字节、word字、dword双字等在硬件中的表达与处理机制。

之所以要强调“码元”的概念,是因为字符编码作为一串数字序列,最终还是得通过机器硬件层面的数据类型来表示。

而码元的实质,就是机器硬件层面的数据类型;不同的码元,代表着不同位数的数据类型。当字符编码方案设计人员基于某种考虑(如时间复杂度、空间复杂度等)为某种字符编码方式CEF选择了某种码元时,其实质就是选择了某个位数的数据类型。

数据类型,在机器硬件层面上来看,只有作为一个整体来处理的二进制数字位数上的不同(如byte字节、word字、dword双字等汇编语言的数据类型,都是二进制数字值,只是位数不同而已),而并没有高级语言层面上的数值、布尔、字符等语义的不同,毕竟本质上来讲计算机只“认识”由0和1组成的数字。

正因为如此,字符编码方案设计人员在设计字符编码方式CEF时,必然要选择一种机器硬件层面上某个位数的数据类型(如byte字节、word字、dword双字等)来表示,不是选择这个位数的数据类型,就是选择那个位数的数据类型。当然这种选择会基于各种考虑,比如时间复杂度、空间复杂度等,不过一旦选择了某种数据类型,其所选择的数据类型位数上的不同,同时也就体现为了码元位数上的不同。

所以,不同位数的码元,实质上是机器硬件层面上不同位数的数据类型。(而机器硬件层面上为什么要设计不同位数的多种数据类型出来,这是另一个话题了,有兴趣可参看有关硬件方面的专著。)

3.

由于数据类型有单字节与多字节之分,所以码元也有单字节与多字节之分;而多字节数据类型由于历史的原因,存在着字节序的大端序(Big-Endian)与小端序(Little-Endian)之分,因此多字节码元也存在着大端序与小端序之分(具体详见前文中有关字节序的解释;注意,单字节数据类型是没有字节序的问题的,所以单字节码元也就没有字节序问题)。

这就是之所以要强调“码元”这个概念的关键原因。

4.

对字符编号(即字符码点值)进行编码的具体实现方式——字符编码方式CEF,就是由一个或多个码元这样的最小基本单元构成的。

最常用的码元是8位(即1字节)的单字节码元,另外还有16位(即2字节)和32位(即4字节)两种多字节码元,分别相当于汇编语言中的byte字节、word字、dword双字,以及C++中的无符号整型BYTE、WORD、DWORD。

(注: 在VC++6.0中,这三种数据类型的定义分别为:

   typedef unsigned char BYTE; // 1个字节

   typedef unsigned short WORD; // 2个字节

   typedef unsigned long DWORD; // 4个字节)

(笨笨阿林原创文章,转载请注明出处)

5.

于是,三种码元对应就有了Unicode字符编号的三种UTF编码方式(即Unicode码转换格式Unicode Transformation Format,或称通用字符集转换格式UCS Transformation Format):

   UTF-8,即8-bit Unicode/UCS Transformation Format;

   UTF-16,即16-bit Unicode/UCS Transformation Format;

   UTF-32,即32-bit Unicode/UCS Transformation Format。

或者反过来说,Unicode字符编号的三种UTF编码方式(UTF-8、UTF-16、UTF-32)分别采用了不同的码元(单字节、双字节、四字节)来编码。

例如,“汉字”这两个中文字符的Unicode字符编号是0x6C49和0x5B57,其三种UTF编码在VC++6.0中可按如下定义进行“模拟”:

6.

注意,这里之所以说是“模拟”,其中的一个重要原因,如前文所述,从本质上来讲机器硬件层面上的所有数据类型,只存在着被视作一个整体来处理的比特序列(即二进制序列)的位数不同之分,不存在着高级语言层面上数据类型的数值、字符串、布尔值等的语义不同之分。

因此,机器硬件层面上的数据类型与高级语言层面上的数据类型,严格来讲,在含义上还是有着很大不同的。当然,高级语言层面上的数据类型最终还是会被转化为机器硬件层面上的数据类型,毕竟计算机只“认识”由0和1所组成的比特流。(可同时参见前文中有关字节序的解释)

7.

这里用BYTE、WORD、DWORD分别表示无符号8位整数、无符号16位整数和无符号32位整数;因而UTF-8、UTF-16、UTF-32可认为分别以BYTE、WORD、DWORD作为码元。

“汉字”这两个中文字符的UTF-8编码需要六个BYTE(共6个单字节码元),大小是6个字节;UTF-16编码需要两个WORD(共2个双字节码元),大小是4个字节;UTF-32编码需要两个DWORD(共2个四字节码元),大小是8个字节。

由于多字节数据类型的数据在计算机存取时存在一个字节序的问题,因此,UTF-16、UTF-32这两种编码方式所编码出来的逻辑意义上的多字节码元序列,在映射为物理意义上的字节序列时,字节序列的字节序因系统平台的不同而不同。

前面已经多次强调过了,这里再次特别强调一下:由单字节数据类型所组成的多字节数据是不存在字节序的问题的。因此,采用单字节码元进行编码的UTF-8编码,虽然ASCII字符为单字节编码,而非ASCII字符却是多字节编码的,但却并不存在字节序问题,这是跟同样为多字节编码、但却采用多字节码元的UTF-16、UTF-32编码的不同之处。详见下表所列。

     Unicode字符集三大编码方式(UTF-8、UTF-16、UTF-32)比较一览表

(笨笨阿林原创文章,转载请注明出处)

 

【预告:下一篇将重点讲解UTF-8编码方式与字节序标记(BOM),敬请关注!

 

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

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

相关文章

【转】刨根究底字符编码之十一——UTF-8编码方式与字节序标记BOM

一、UTF-8编码方式 1. 接下来将分别介绍Unicode字符集的三种编码方式:UTF-8、UTF-16、UTF-32。这里先介绍应用最为广泛的UTF-8。 为满足基于ASCII、面向字节的字符处理的需要,Unicode标准中定义了UTF-8编码方式。UTF-8应该是目前应用最广泛的一种Unic…

流水灯verilog实验原理_IC设计实例解析之“流水线技术”

源自:微信公众号 “数字芯片实验室”在IC设计中,如果寄存器之间的组合逻辑延时过大,可能会称为设计中的关键路径,从而降低整个电路的工作频率。如下图所示,是一个输入和输出寄存的算术计算逻辑。在set_input_delay和se…

【转】刨根究底字符编码之十二——UTF-8究竟是怎么编码的

UTF-8究竟是怎么编码的 1. UTF-8编码是Unicode字符集的一种字符编码方式(CEF),其特点是使用变长字节数(即变长码元序列或称变宽码元序列)来编码。目前一般是1到4个字节,当然,也可以更长。 为什么要变长呢?这可以理解为按需分配…

iphone闪退修复工具_升级 iOS 14.2 微信闪退?iPhone 12 维修贵

原标题:升级 iOS 14.2 微信闪退?iPhone 12 维修贵昨天,苹果推出 iOS 14.2 正式版系统,我相信你们都知道了,主要新增几点功能,并没有针对性解决耗电问题,而对 AirPods Pro 充电进行优化&#xff…

【转】刨根究底字符编码之十三——UTF-16编码方式

1. UTF-16编码方式源于UCS-2(Universal Character Set coded in 2 octets、2-byte Universal Character Set)。而UCS-2,是早期遗留下来的历史产物。 UCS-2将字符编号直接映射为字符编码(CEF,而非CES,详见前文中对现代字符编码模型的解释)&a…

java xml 默认名称空间 xpath_创意产业园办公空间设计

你说想要的样子永远不是现在你的样子,桃花源或许永远在每个人的心底。桃花源办公空间整体外观入口前厅及走廊空间天花板细节桃花源其实是我们每个人或者一群人的乌托邦,一座苏联式的厂房是心中桃花源的开端,光、空、间、穿、行、高、纵、新、…

【转】刨根究底字符编码之十四——UTF-16究竟是怎么编码的

1. 首先要注意的是,代理Surrogate是专属于UTF-16编码方式的一种机制,UTF-8和UTF-32是不用代理的。 如前文所述,为了让UTF-16能继续编码基本平面后面的增补平面中的码点值,于是扩展了UTF-16编码方式。 具体的扩展方法就是为其增…

java环境_配置java环境变量

1.找到此电脑我的电脑右键属性。2.点击高级系统设置。3.点击环境变量。4.点击新建。5.创建变量名JAVA_HOME必须是大写,变量值找到你的jdk的根目录复制下来,然后粘贴进去,点击确定。6.再次点击新建7.创建变量名为path、变量值,找到…

idea+JRebel实现项目热部署

今天发现这个插件,简直神了,太爽了,每次改完代码重启都要等半天,回不去了 第一步:安装插件 第二步:在线生成GUID 网址:在线GUID地址 第三步:打开jrebel 如下所示面板,选…

【转】刨根究底字符编码之十五——UTF-32编码方式

1. UTF-32在UTF目前常用的三种编码方式(UTF-8、UTF-16、UTF-32)中,是最为简单的一种编码方式。UTF-32编码方式不使用任何编码算法将Unicode字符码点值(即编号字符集CCS中的字符编号)转换为码元序列,而是将每个Unicode字符码点值直接表示为一个32位的码元…

小米手机证书信任设置在哪里_小米手机闹钟在哪里?闹钟怎么设置?怎么找到闹钟?...

随着智能手机的大量普及,人们会发现手机里的功能越来越多,绝不像以前那样只能打打电话发发短信那么简单了。而这些功能当中很多我们常用的功能有的人却不会用、不会设置,甚至根本找不到在哪里?比如说手机闹钟这个功能,…

【转】刨根究底字符编码之十六——Windows记事本的诡异怪事:微软为什么跟联通有仇?

1. 当用一个软件(比如Windows记事本或Notepad)打开一个文本文件时,它要做的第一件事是确定这个文本文件究竟是使用哪种编码方式保存的,以便于该软件对其正确解码,否则将显示为乱码。 一般软件确定文本文件编码方式的方法有如下三种&#xf…

win10切换输入法快捷键_输入法失灵怎么办?该怎么恢复?

我们都尝试过在使用win10的时候,输入法无法切换,只能打英文不能输入汉字,对于要打字、打游戏来说都是非常麻烦的。所以,当输入法有问题的时候,应该要怎么样修复?主编:渣渣辉,是兄弟就…

【转】刨根究底字符编码【2.0版】(1):开篇

首先跟大家分享一个有趣的亲身经历。有一次,在网上我看到有程序员发了一个帖子,帖子题目乍一看让人感到惊愕,但细一想又让我会心一笑。 这个帖子的题目大致上是这样的:字符编码是不是让程序员最感到恶心的问题? 更有…

数位dp模板 最高位最低位_无纸化办公入门指南(数位板篇)

居家办公的这段时间,你们有没有遇到无纸化办公的问题?作为一名编辑,在我社规定不能寄纸稿的情况下,看电子稿成了常态。如果是word版尚且可以批注,不影响工作效率。但如果是PDF呢?怎样保证改稿的效率&#x…

AQS

1 AQS抽象的队列同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch 首先AQS维护了一个volatile 修饰的state和一个FIFO的同步队列(多线程争用资源被…

屏幕录像专家6.0_迅捷屏幕录像工具和屏幕录像专家哪个更好用?

随着社会的发展,屏幕录像常常都需要使用,然而有些新手朋友就想知道,到底是电脑中自带的屏幕录像专家好用,还是迅捷屏幕录像工具好用,这两者都是当前使用率比较高的软件,今天小编就为大家分析分析&#xff0…

【转】刨根究底字符编码【2.0版】(2):关键术语解释

上一篇中讲道,字符编码所涉及的面非常广,向下的话,涉及到计算机的底层技术,甚至是硬件实现。 因此,这里就让我们从字符编码涉及到的最基本的术语讲起。大部分术语你可能都已经有了解了,但我们现在从字符编…

Cause: java.sql.SQLSyntaxErrorException: Table ‘Chun.user‘ doesn‘t exist Springboot+MybatisPlus报错

排错:yml配置没问题,可以连接到数据库,导包没问题,数据库里面也有这个库和表, 最终发现是因为表名大小写的问题,因为我直接连接的阿里云服务器上的mysql,而mysql在linux下表名是区分大小写的导…

浏览器字体大小设置_CSS之 浏览器解析样式的过程

阅读本文约需要10分钟大家好,我是你们的导师,经常看我朋友圈的同学应该知道,我每天会在微信上给大家免费提供以下服务!1、长期为你提供最优质的学习资源!2、给你解决技术问题!3、每天在朋友圈里分享优质的技…