UTF-16

来自GSXAB的知识库
UTF-16
术语名称 UTF-16
英语名称 UTF-16

UTF-16 是一个将 Unicode 字符集编码为双字节流的字符编码方法。 UTF 即 Unicode Transformation Format , Unicode 传输格式。

这一编码是变长编码,每一个 Unicode 码位会被编码为一个到两个双字节。其中 Unicode 基本多文种平面 BMP 中的字符总是一个双字节,而辅助平面中的字符才会被编码为两个双字节,这使得多字节的情况相对难以覆盖,在历史上出现过很多相关的边缘场景问题。由于其表示方式是双字节,是少见的与 ASCII 明确不兼容且仍在大范围使用的现代编码方式。 UTF-16 是唯一一种万维网中仍被允许的与 ASCII 不兼容的编码,而且使用比例极少, UTF-8 可以看作是其主要替代品。

最初还不清楚 [math]\displaystyle{ 2^16 }[/math] 对于一个统一字符集还不充足时, Unicode 字符集 UCS 使用双字节,并且直接使用双字节编码,现在将这种历史编码称为 UCS-2 (最初曾直接称为 Unicode)。在逐渐发现这一问题时, IEEE 引入了更大的 31 位编码空间,及其中编码 UCS-4 ,但是当时已经有大量关于每字符 2 字节的研究,且每字符 4 字节会对内存有相当额外的消耗量,因此作为让步,在 Unicode 2.0 中引入了 UTF-16 。

编码规则

UTF-16 中,全部的二进制表示都是以双字节为单位的。

双字节的 0x00-FF.00-FF 可以对应编码 U+0000-FFFF 范围,可以直接编码基本多文种平面 BMP 的字符。

BMP 中留出一个特殊的区块 U+D800-DFFF ,称为代理项(surrogate),包含高代理 U+D800-DBFF 和低代理 U+DC00-DFFF 两种,这些码位高低成对构成代理对(surrogate pair)。 这些码位只能成对使用,作为单独使用的字符时不视为合法码位,只是“半个代理对”这样的不合法内容。 当一组代理对在一起时,可以写成二进制形式 0x1101 10??.???? ????.1101 11??.???? ???? ,可以看出其中共有 20 个可变二进制位。 在表达辅助平面的码位时,先从码位上减去偏移量 10000H ,使 U+10000-10FFFF 落在 0HFFFFFH 之间,也就是只剩下 20 个二进制位,然后将其嵌入这个代理对的这 20 个二进制位中。

特征

UTF-16 中通过一到两个双字节编码 Unicode 码位,除了代理项区块以外,直接表示对应码位;而高代理项代表一个辅助平面码位的前一半,低代理项代表一个辅助平面码位的后一半,两者只能成对连续出现。这使得 UTF-16 是一种有自同步能力(即:通过任意截断的双字节都可以确认下一个字符起始单元的位置,不会发生错位)的前缀码。

不支持使用代理对的编码称为 UCS-2 ,是一个已过时编码方案。

错误处理

由于单字节和代理对到 BMP 和辅助平面是一一对应关系, UTF-16 中不存在代理对共同构成不合法码位问题造成的编码错误,存在的主要错误是代理对不匹配。默认情况下,大多数编解码实现中还是会使用与其对应的半个代理对作为字符。

BOM

UTF-16 (以及 UCS-2)是以双字节为单位读写的,由于大多数储存传输协议中基本单位都是字节,因此存在字节序问题。

如果允许指定字节序,大端(big-endian, BE)和小端(small-endian, LE)的编码分别被称为 UTF-16BE 和 UTF-16LE (类似地有 UCS-2BE 、 UCS-2LE)。在编码类型中指定字节序时,不要求带有字节序标记。

若字节序无法指定,默认需要一个字节序标记 U+FEFF Byte Order Mark 在流头部来确定字节序。在 Unicode 中, U+FEFF 是保留给字节序的功能字符,而 U+FFFE 是保留的未编码的功能字符,因此只要查看前两个字节构成其中的哪一个就能确认当前文档中的字节序。

若字节序未指定的同时,又缺少字节序标记 BOM ,也就是前两个字节既不是 0xFE.FF 也不是 0xFF.FE ,此时 RFC 2781 推荐将大端作为默认编码。但是由于 Windows 等环境默认小端,不少实现中也会将小端作为默认的字节序。


常见字符集字符编码
原始编码 电报码( Morse 电码 BCD 码IBM 卡编码 -
早期二进制码位分配的编码 - BCDICEBCDIC ASCIIISO 646-US 、 ISO 646-IRV)
地区字符编码 - - ISO 8859 : ISO 8859-1 、 ISO 8859-2 、……
- - EUC 类编码,含第一个国标字符集 GB 2312
其编码 EUC-CNIBM 代码页 936)也称 GB 2312
多地区字符编码通过切换串兼容 - - 通用框架: ISO 4873ISO 2022 ,含 ISO-2022-CN
ISO-2022-CN 的简化: HZ 编码
无需切换串的自同步编码 - UTF-EDCBIC 字符集 Unicode / ISO 10646 ,有常见编码 UTF-8UTF-16UTF-32 及废弃编码 UTF-1UTF-7
地区字符编码扩充 - - 国标系列后续:GBK微软代码页 936)、 GB 18030微软代码页 54936

参考资料

https://en.wikipedia.org/wiki/UTF-16