以下内容主要来自腾讯元宝。

UTF-16 是一种 以16位码元为基本单位变长字符编码,用于表示Unicode字符集。它的核心设计是在内存效率和编码复杂度之间取得平衡,并成为Windows、Java、.NET、JavaScript等核心平台内部字符串表示的事实标准

一、 核心设计:基本平面与代理对 

  1. 基于16位码元:基本处理单位是16位(2字节),而非单个字节。
  2. “准定长”设计:绝大部分常用字符(位于基本多文种平面)固定用1个16位码元表示。这使得在处理这些字符时,其行为类似于定长编码,效率较高。
  3. 代理对机制:对于较少使用的字符(位于辅助平面),使用2个特殊的16位码元(称为“代理对”)来表示。这是其“变长”特性的来源。
  4. 存在字节序问题:由于以16位为单位,存储和传输时需要明确字节顺序(大端序或小端序),通常通过BOM或协议约定来解决。

UTF-16编码空间直接映射到Unicode的17个平面,将Unicode字符分为两类,采用不同的编码策略:

Unicode 码点范围

平面

UTF-16 编码方式

字节长度

示例

U+0000 ~ U+FFFF
(不包括 U+D800~U+DFFF

基本多文种平面(BMP内的字符,即第0平面)

直接映射。码点值直接作为一个16位码元。

一个码元即2字节

包含绝大多数现代语言字符、常用汉字、符号等。例如,“中”(U+4E2D)的UTF-16编码就是 4E 2D(两个字节)。

U+10000 ~ U+10FFFF

辅助平面(第1~16平面)

代理对。使用两个特殊的16位码元组合表示。

2个码元即4字节

包含历史文字、罕见汉字、表情符号等。编码过程需要计算。

代理对计算机制

  1. 对于辅助平面字符(如 U+1F60A):
  2. 码点值 - 0x10000,得到20位中间值(0x0F60A)。
  3. 高10位:(中间值 >> 10) + 0xD800高代理​ (0xD83D)。
  4. 低10位:(中间值 & 0x3FF) + 0xDC00低代理​ (0xDE0A)。

二、 关键特性与影响 

1.字节序问题

由于基本单位是16位(2字节),存储和传输时必须明确字节顺序(大端序或小端序)。

通常通过字节顺序标记(BOM,U+FEFF)在文件/数据流开头声明:

FE FF:表示大端序(UTF-16BE)。

FF FE:表示小端序(UTF-16LE,Windows常用)。

2.编程语言中的实现

Java & .NET:String和 char类型内部使用UTF-16。一个 char存储一个16位码元,因此辅助平面字符(如表情)会占用两个 char。

JavaScript:ECMAScript标准规定字符串为UTF-16编码。

Windows API:原生宽字符API(LPCWSTR, wchar_t)使用UTF-16。

C++11:引入 char16_t类型和 std::u16string明确表示UTF-16字符串。

3.主要优势

处理效率:对于BMP内的字符(涵盖绝大多数现代文字),它是定长2字节,便于计算和随机访问(在忽略代理对的情况下)。

空间权衡:存储常见非拉丁文字(如中文、日文、韩文)时,比UTF-8更节省空间(UTF-8需3字节,UTF-16为2字节)。

系统深度集成:与底层操作系统(尤其是Windows)和运行时(JVM、CLR)的API无缝兼容。

三、 核心挑战与陷阱 

变长复杂性:必须正确处理代理对。任何基于“固定2字节”假设的字符串操作(如截断、反转、随机索引访问)都可能破坏编码。

长度语义混淆

码元数:字符串中16位单元的数量(Java的 .length()返回此值)。

字符数:实际的Unicode码点数量。

一个辅助平面字符(如“😊”)的码元数为2,字符数为1。

与ASCII不兼容:纯ASCII文本在UTF-16中体积会翻倍,且包含大量零字节,不适合作为通用交换格式。

四、 与UTF-8的对比及选型指南 

维度

UTF-8

UTF-16

基本单位

8位字节

16位码元

BMP字符长度

变长(1-3字节)

固定2字节

辅助平面长度

4字节

4字节

字节序

有(需BOM)

ASCII兼容性

完全兼容

不兼容(2字节/字符)

英文文本效率

极高(1字节/字符)

低(2字节/字符)

中文文本效率

通常3字节/字符

固定2字节/字符(BMP内)

主要适用场景

存储、传输、网络协议
(JSON, HTML, 文件系统)

系统内部表示、内存处理
(Windows API, Java/.NET运行时)

黄金实践法则

对外(存储/传输/交换)一律用UTF-8:它是互联网的通用语,无字节序问题,空间效率高。

对内(特定系统/平台内部)按需使用UTF-16:当您深度开发Windows原生应用、Java/.NET程序或处理JavaScript引擎内部时,需遵循其UTF-16的模型。

五、 总结 

UTF-16是一种为系统级软件和运行时环境优化的Unicode编码。它通过代理对机制在保持BMP内字符处理简便性的同时,扩展了对全部Unicode字符的支持。开发者必须清醒认识其“16位码元变长”的本质,警惕代理对和字节序带来的复杂性。在当今技术栈中,它通常不作为数据交换的终点,而是作为特定生态系统内部高效处理的中间表示层

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐