无需登录 数据私有 本地保存

UTF-16编码解码工具 - 字符与十六进制序列互转

130
0
0
0
Unicode

Unicode是一种国际标准字符编码系统,旨在为世界上几乎所有书写系统的每个字符分配一个唯一的数字标识符(即码点,Code Point)。截至最新的Unicode 15.1版本,Unicode标准已经定义了超过149,000个字符,覆盖了161种文字系统。Unicode的码点范围从U+0000到U+10FFFF,总共可以表示超过111万个字符。Unicode标准由Unicode联盟(Unicode Consortium)负责维护和更新,该联盟由全球主要的科技公司和标准化组织组成。

Unicode本身只定义了字符的码点编号,并不规定这些码点如何在计算机中存储和传输。为了将Unicode码点映射为字节序列,需要使用具体的编码方案。UTF-8、UTF-16和UTF-32是三种主要的Unicode编码形式,它们各有特点和适用场景。理解Unicode编码标准是理解所有字符编码问题的基础,也是使用本工具进行UTF-16编码转换的前置知识。

UTF-16编码单元与码元

UTF-16的编码单元(Encoding Unit)或码元(Code Unit)是16位(2字节)的数据单元,是UTF-16编码的基本构建块。每个UTF-16码元可以表示从0x0000到0xFFFF范围内的值。对于Unicode基本平面(BMP)中的字符,一个UTF-16码元就足以表示完整的字符信息。UTF-16码元的概念类似于UTF-8中的8位编码字节,但宽度不同(16位 vs 8位)。理解码元概念对于区分"字符数"和"码元数"这两个统计指标至关重要——对于补充字符,一个字符对应两个码元。

基本多文种平面(BMP)

基本多文种平面(Basic Multilingual Plane,简称BMP)是Unicode编码空间的第一个平面,码点范围为U+0000到U+FFFF,包含65,536个码点。BMP覆盖了世界上绝大多数常用文字的字符,包括拉丁字母、希腊字母、西里尔字母、阿拉伯字母、中文汉字(约97,000个常用汉字中的大部分)、日文假名、韩文谚文以及各种数学符号和标点符号。在UTF-16编码中,BMP字符可以用单个16位码元直接表示,无需使用代理对机制。这也是UTF-16在处理CJK文字时效率最高的原因——中文字符在UTF-16中占用2字节,而在UTF-8中需要3字节。

代理对(Surrogate Pair)

代理对是UTF-16编码中用于表示补充平面字符的机制。由于UTF-16的基本编码单元是16位,直接表示的范围仅为0x0000到0xFFFF(即BMP),无法覆盖Unicode标准中U+10000到U+10FFFF范围内的补充字符。为解决这个问题,UTF-16引入了代理对概念:使用两个连续的16位码元来表示一个补充字符。第一个码元称为高代理(High Surrogate),范围为U+D800到U+DBFF;第二个码元称为低代理(Low Surrogate),范围为U+DC00到U+DFFF。通过这种机制,UTF-16可以表示完整的Unicode字符集。

代理对的工作原理涉及一个数学转换。以emoji "😀"(U+1F600)为例,首先计算偏移量:0x1F600 - 0x10000 = 0xF600。然后将偏移量拆分为高10位和低10位:高10位为0x3D,低10位为0x200。高代理值 = 0xD800 + 0x3D = 0xD83D,低代理值 = 0xDC00 + 0x200 = 0xDE00。因此,"😀"在UTF-16中的编码为D83D DE00。这种编码方式保证了代理对的码元值永远不会与有效的BMP字符码元混淆。

字节序(Byte Order)

字节序是指多字节数据在计算机内存或存储中的字节排列顺序。对于UTF-16的2字节编码单元,存在两种可能的排列方式。小端序(Little-Endian,LE)将低字节存储在低地址(或低字节在前),例如码元0x4E2D在内存中存储为2D 4E。大端序(Big-Endian,BE)将高字节存储在低地址(或高字节在前),同一码元0x4E2D存储为4E 2D。不同的CPU架构可能采用不同的字节序:x86/x64处理器采用小端序,而某些RISC处理器和网络协议使用大端序。字节序不匹配会导致数据解析错误,因此在跨平台数据交换时必须明确指定或自动检测字节序。

BOM(字节顺序标记)

BOM(Byte Order Mark)是Unicode标准定义的一个特殊字符U+FEFF,用作字节顺序标记。BOM放置在文本的最前面,其字节表示本身就能揭示文本的字节序。在UTF-16LE编码中,BOM表示为FF FE;在UTF-16BE编码中,BOM表示为FE FF。读取器在打开文件时首先检查开头的这两个字节,如果发现FF FE则按小端序解析后续数据,如果发现FE FF则按大端序解析。BOM机制的优点是提供了明确的、自动化的字节序检测能力,缺点是在某些场景下(如Unix/Linux系统或HTTP头部处理中)BOM可能被视为多余或产生兼容性问题。

高代理与低代理

高代理(High Surrogate)和低代理(Low Surrogate)是UTF-16代理对中的两个组成部分。高代理码元的范围为U+D800到U+DBFF,共1,024个值;低代理码元的范围为U+DC00到U+DFFF,同样是1,024个值。高代理和低代理的组合可以表示1,024 × 1,024 = 1,048,576个补充字符,加上BMP的65,536个字符,UTF-16总共可以表示1,114,112个字符,正好覆盖Unicode标准定义的整个码点空间。在编码时,必须确保高代理在前、低代理在后,任何违反这一顺序的编码都是无效的UTF-16。

UCS-2

UCS-2(Universal Character Set 2-byte)是Unicode早期采用的固定长度2字节编码方案,可以视为UTF-16的前身。UCS-2使用固定的2字节编码所有字符,因此只能表示BMP中的65,536个字符。当Unicode标准需要表示超过65,536个字符时,UCS-2无法扩展,于是被UTF-16所取代。UTF-16在UCS-2的基础上增加了代理对机制,实现了向后兼容——任何有效的UCS-2编码也是有效的UTF-16编码。在一些历史文献和技术讨论中,UCS-2和UTF-16有时会被混用,但在现代技术语境中,两者有本质的区别。

UTF-8 vs UTF-16

UTF-8和UTF-16是两种最常用的Unicode编码方案,各有优劣。UTF-8使用1到4个字节变长编码,对于ASCII字符(U+0000到U+007F)仅需1字节,是Web内容和互联网传输的事实标准。UTF-16使用2到4字节变长编码,对于BMP字符固定使用2字节,在处理CJK文字时效率更高(中文字符UTF-16占2字节,UTF-8占3字节)。选择编码方案时需要考虑具体应用场景:如果文本主要是英文或ASCII内容,UTF-8更高效;如果文本主要是中文、日文等CJK文字,UTF-16可能更高效;如果是Web页面或需要与大量遗留系统交互,UTF-8的兼容性更好。

代理对安全(Surrogate Pair Safety)

代理对安全是指在文本处理过程中正确处理UTF-16代理对的实践和要求。由于补充字符由两个码元(高代理和低代理)组成,如果文本处理逻辑不当——例如在代理对的中间位置进行截断、逐码元地迭代文本或使用单个16位值来表示本应是代理对的字符——就会产生所谓的孤立代理(Lone Surrogate),导致文本损坏或安全漏洞。在JavaScript等语言中,错误地处理字符串长度(String.length返回的是码元数而非字符数)是常见的代理对安全问题。正确的做法是使用感知代理对的字符串操作方法,如Array.from()或正则表达式的/u标志。