【转】刨根究底字符编码之十三——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,详见前文中对现代字符编码模型的解释),亦即字符编号就是字符编码,中间没有经过特别的编码算法转换。因此,从现代字符编码模型的角度来看的话,此时并没有将编号字符集CCS与字符编码方式CEF作严格区分,既可以将UCS-2看作是编号字符集CCS中的字符编号,也可以看作是字符编码方式CEF中的字符编码。

后来,随着Unicode联盟与ISO/IEC就创建全球统一的单一通用字符集进行合作,Unicode字符集与UCS字符集逐渐相互融合,两者最终基本保持了一致(详见前文《刨根究底字符编码之八——Unicode编码方案概述》中的介绍)。

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

2.

这之后,Unicode逐渐占据了主导地位,并引入了UTF-16编码方式。为什么要引入UTF-16编码方式呢?

前文已经介绍过了,Unicode字符集(CCS)到目前为止定义了包括1个基本平面BMP和16个增补平面SP在内的共17个平面。

每个平面的码点数量为2^16=65536个,因此17个平面的码点总数为共65536*17=1114112个。其中,基本平面码点为65536个(码点编号范围为0x0000~0xFFFF),增补平面码点为1114112-65536=65536*16=1048576个(码点编号范围为0x10000~0x10FFFF)。

很明显,简单地用一个16位码元肯定无法表示所有17个平面的这么多码点(因为2^16=65536,而码点总数为65536*17=1114112)。而UCS-2,正是用两个字节共16位来表示一个字符的。为支持字符编号超过U+FFFF的增补字符,扩展势在必行。

3.

UCS因而又提出了UCS-4,即用四个字节共32位来表示一个字符(此时UCS-4同样既可认为是编号字符集CCS中的字符编号,也可认为是字符编码方式CEF中的字符编码)。但码元也因此从16位扩展到了32位。

而Unicode却提出了不同的扩展方式——代理机制。具体而言,就是为了能以一个统一的16位码元同时编码基本平面以及增补平面中的字符码点编号,Unicode设计引入了UTF-16编码方式,并且通过代理机制实现了扩展。

UTF-16编码方式的引入,从现代字符编码模型的角度来看的话,彻底将编号字符集CCS与字符编码方式CEF作了严格区分。也就是说,在UTF-16编码方式中,编号字符集CCS中的字符编号与字符编码方式CEF中的字符编码不再仅仅是简单的直接映射关系。

具体来说,就是Unicode字符集基本平面BMP中的字符(大致相当于UCS字符集中的UCS-2字符,但必须除开U+D800~U+DFFF这一在Unicode字符集BMP中称之为代理码点的部分),仍然是直接映射关系,亦即这部分字符的字符编号与字符编码是等同的。

但Unicode字符集增补平面中的字符(大致相当于UCS字符集UCS-4字符中除开UCS-2字符的部分,因为广义上的UCS-4字符实际上包含了UCS-2字符,当然狭义上的UCS-4字符不包括UCS-2字符),却不是直接映射关系,而是必须通过代理机制这一编码算法的转换,亦即这部分字符的字符编号与字符编码不是等同的。

因此,在Unicode引入了UTF-16编码方式之后,站在现代字符编码模型的角度上来看的话,再将UCS-2和UCS-4直接称之为字符编码方式CEF已不是很合适,更多的应该是编号字符集CCS中的概念(当然,在了解其历史原因之后,将UCS-2和UCS-4同时理解为编号字符集CCS和字符编码方式CEF也未尝不可);而若将UCS-2等同于UTF-16,将UCS-4等同于UTF-32(后文会有介绍),显然也是不合适的。

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

4.

UTF-16中的所谓代理机制,实际上就是用两个对应于基本平面BMP代理区(Surrogate Zone)中的码点编号的16位码元来表示一个增补平面码点,这两个用来表示一个增补平面码点的特殊16位码元被称之为代理对(Surrogate Pair)(解释详见后文《UTF-16究竟是如何编码的——UTF-16的编码算法详解》)

UTF-16编码方式及其代理机制是在Unicode 2.0中为支持字符编号超过U+FFFF的增补字符而引入的,于是从此就由UCS-2的等宽(16位)码元序列编码方式(如前文所述,从现代字符编码模型的角度来看的话,UCS-2更多是的编号字符集CCS中的概念,但考虑到其历史原因,称之为字符编码方式CEF亦未尝不可,下同,不再赘述),变成了UTF-16的变宽(16位或32位)码元序列编码方式。不过,码元依然保持了16位不变。

5.

UCS-2所编码的字符集中的U+D800~U+DFFF这部分代理码点除外的话,UTF-16所编码的字符集可看成是UCS-2所编码的字符集的父集。

在没有引入增补平面字符之前,UTF-16与UCS-2(U+D800~U+DFFF这部分代理码点除外)的编码完全相同。但当引入增补平面字符后,UTF-16与UCS-2的编码就不完全相同了(事实上,由于UCS-2只有两个字节,根本无法编码增补平面字符)。

现在若有软件声称自己支持UCS-2编码,那相当于是在暗示其仅支持UCS字符集或Unicode字符集中的基本平面字符,而不能支持增补平面字符。

6.

所以说,UTF-16是变长编码方式,每个字符编码为16位或32位;而UCS-2是定长编码方式,每个字符编码固定为16位。但两者的码元却都是16位的(而UTF-32和狭义的UCS-4的码元都是32位的)。

另外,UTF-16中,大部分汉字采用两个字节编码,少量不常用汉字采用四个字节编码。

Windows 2000及之后的版本是支持UTF-16的,之前的Windows NT/95/98/ME是只支持UCS-2的。

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

7.

作为逻辑意义上的UTF-16编码(码元序列),由于历史的原因,在映射为物理意义上的字节序列时,分为UTF-16BE(Big Endian)、UTF-16LE(Little Endian)两种情况。比如,“ABC”这三个字符的UTF-16编码(码元序列)为:00 41 00 42 00 43;其对应的各种字节序列如下:

Windows平台下的UTF-16编码(即上述的FF FE 41 00 42 00 43 00) 默认为带有BOM的小端序(即Little Endian with BOM)。你可以打开记事本,写上ABC,保存时选择Unicode(这里的Unicode实际上指的是UTF-16 Little Endian with BOM,即带BOM的UTF-16小端序CES编码,详见后文解释)

然后保存,再用UltraEdit编辑器看看它的编码结果:

Windows从NT时代开始就采用了UTF-16编码方式,很多流行的编程平台,例如.Net、Java、Qt还有Mac下的Cocoa等都是使用UTF-16作为基础的字符编码。例如代码中的字符串,在内存中相应的字节流就是UTF-16字节序列的。(注意,UTF-16编码在Windows环境中被误用为“widechar”和“Unicode”的同义词)

8.

UTF-16一方面使用变长码元序列的编码方式,相较于定长码元序列的UTF-32算法更复杂(甚至比同样是变长码元序列的UTF-8也更为复杂,因为引入了独特的代理对这样的代理机制);另一方面仍然占用过多字节,比如ASCII字符也同样需要占用两个字节,相较于UTF-8更浪费空间和带宽。

因此,UTF-16在Unicode字符集的三大编码方式(UTF-8、UTF-16、UTF-32)中表现较为糟糕。它的存在是历史原因造成的,引起了很多混乱。不过由于其推出时间最早,已被应用于大量环境中,目前虽然不被推荐使用,但长期来看,作为程序人员都不得不与之打交道。因而,对于其具体的编码算法的了解是十分必要的,本系列文章的下一篇将详细介绍其复杂的编码算法(主要是代理编码算法)。

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

(未完待续)

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

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

相关文章

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、每天在朋友圈里分享优质的技…

angular实现国密算法sm2、sm3和sm4的ts版,基于sm-crypto库实现,前后端实现

ts版,js的话直接根据npm文档调用就可以了! ts提供的方法有问题,所以还换了个思路来实现!而且因为不是nodeJs环境所以const sm4 require(sm-crypto).sm4这个在ts里是报错的导致无法实现,如果是使用的是electron那么使…

【转】.net异步性能测试(包括ASP.NET MVC WebAPI异步方法)

很久没有写博客了,今年做的产品公司这两天刚刚开了发布会,稍微清闲下来,想想我们做的产品还有没有性能优化空间,于是想到了.Net的异步可以优化性能,但到底能够提升多大的比例呢?恰好有一个朋友正在做各种语…

win7关机快捷键_电脑快捷键大全(上)

Windows快捷键1单独按Windows:显示或隐藏“开始”功能表WindowsBREAK:显示“系统属性“对话框WindowsD显示桌面或回复桌面Windows M最小化所有窗口WindowsShiftM:还原最小化的窗口CrtlShiftN:新建文件夹WindowsE:打开“我的电脑”…

【转】ASP.NET Web API 使用Swagger生成在线帮助测试文档,支持多个GET

以下为教程: 在现有webapi项目中,nuget安装以下两个插件 swagger.net.ui swashbuckle 安装完毕后可以卸载Swagger.NET,此处不需要! 安装完毕后屏蔽以下代码 直接运行调试 在浏览器的目录后面加上/swagger即可跳转到swagger调试页 此时如果没有注释. 项目属性里添加xml注释…

idea提示“ cannot access xxxxxxxx.class“的解决方法,idea的bug

同一个包下的public类使用报错,应该是idea的bug: file -> Invalidate Caches / Restart