如何以字节序不可知的方式读取 UTF-16 代码点的长度
How to read the length of a UTF-16 codepoint in an endian-agnostic way
如果我事先不知道它的字节顺序,我如何才能沿着它的代码点遍历一个 UTF-16 字符串?在我的代码中,此时假定字节顺序已经转换为当前体系结构使用的任何内容,我只想从一个代码点转到下一个代码点。
你不能。考虑字节序列 0xD8 0x3D 0xDE 0x00
:
- 如果它被读取为 UTF-16BE,它是一个单一的代码点:
U+1F600
()
- 如果读作UTF-16LE,就是两个码位:
U+3DD8
U+00DE
(㷘Þ)
这两种解释都是完全正确的,没有一些字节顺序指示器就无法区分它们。
只有知道数据的字节序,才能可靠地计数。
这可以通过确保数据以 unicode BOM 开头来实现:大端是 0xFE 0xFF
,小端是 0xFF 0xFE
。因此,对于您阅读的 16 位字符 wc
,(wc>>8==0xFE
) 会告诉您字节序。
没有 BOM,你永远无法确定它是 BE 还是 LE,除非你在 surrogate pairs 中发现一些编码不一致,这表明你的字节顺序假设是错误的(即 16 位字符在 0xD800-0xDFFF
范围和另一个不符合条件形成代理对)。
您还可以尝试使用一些基本统计数据、使用换行符(如果它是多行文本)或在整个文本中分布空值来进行有根据的猜测(参见示例 this library)。但是无论您找到什么,您都不能真正确定您确定了正确的字节序。
如果我事先不知道它的字节顺序,我如何才能沿着它的代码点遍历一个 UTF-16 字符串?在我的代码中,此时假定字节顺序已经转换为当前体系结构使用的任何内容,我只想从一个代码点转到下一个代码点。
你不能。考虑字节序列 0xD8 0x3D 0xDE 0x00
:
- 如果它被读取为 UTF-16BE,它是一个单一的代码点:
U+1F600
() - 如果读作UTF-16LE,就是两个码位:
U+3DD8
U+00DE
(㷘Þ)
这两种解释都是完全正确的,没有一些字节顺序指示器就无法区分它们。
只有知道数据的字节序,才能可靠地计数。
这可以通过确保数据以 unicode BOM 开头来实现:大端是 0xFE 0xFF
,小端是 0xFF 0xFE
。因此,对于您阅读的 16 位字符 wc
,(wc>>8==0xFE
) 会告诉您字节序。
没有 BOM,你永远无法确定它是 BE 还是 LE,除非你在 surrogate pairs 中发现一些编码不一致,这表明你的字节顺序假设是错误的(即 16 位字符在 0xD800-0xDFFF
范围和另一个不符合条件形成代理对)。
您还可以尝试使用一些基本统计数据、使用换行符(如果它是多行文本)或在整个文本中分布空值来进行有根据的猜测(参见示例 this library)。但是无论您找到什么,您都不能真正确定您确定了正确的字节序。