【问题标题】:Check if byte sequence contains utf-16检查字节序列是否包含 utf-16
【发布时间】:2012-12-21 04:59:36
【问题描述】:

我正在从流中读取字节序列。假设为了论证,序列是固定长度的,我将整个内容读入一个字节数组(在我的例子中是vector<char>,但这对于这个问题并不重要)。这个字节序列包含一个字符串,可以是 utf-16 或 utf-8 编码。不幸的是,没有迹象表明它是哪一个。

我可以验证字节序列是否代表有效的 utf-16 编码以及它是否代表有效的 utf-8 编码,但我也可以想象相同的字节序列如何可能是有效的 utf-8 和有效utf-16 格式。

那么,这是否意味着无法从一般意义上确定它是哪一个?

【问题讨论】:

标签: string unicode utf-8 utf-16


【解决方案1】:

那么,这是否意味着无法从一般意义上确定它是哪一个?

没错。字节串[0x30, 0x30]可以是UTF-8字符串00或字符的UTF-16编码。如果您想知道,那是 WAVY DASH。

还有一些启发式方法可以尝试:

  • 您可以检查字符串是否以 BOM 开头(Windows 程序喜欢这些),因为这两个 BOM 都不是 UTF-8 序列的有效开头。
  • 如果您确定字符串中没有 NUL 字符,则每个包含零字节的偶数长度字符串都必须是 UTF-16。

如果失败,您必须默认使用其中一个选项,或者在使用 -8 和 -16 解码时对字符串的内容进行某种检查。

【讨论】:

  • 大部分 UTF-16 字符串不是有效的 UTF-8。根据您期望的输入类型,可用的启发式方法可能是默认为 UTF-8,但如果您看到无效序列,则回退到 UTF-16(但是哪种?)。如果每个其他字节都是一个常量,或者来自几个常量的受限曲目,那么这也可能是一个有用的观察(零字节在技术上是有效的 UTF-8,但如果每隔一个字节都是零,那就是强 UTF- 16 提示)。
  • @triplee 不幸的是,无法控制该字符串的含义。我所知道的是它是一个文本字符串,它可以是 any 脚本中的 any 语言(包括 RTL 脚本)。
  • 这并不会真正影响上面的启发式方法,但是如果输入可以只是几个字节,那么就没有什么可做的了。
  • @triplee:是的。我认为“这是正确的”是答案的主要部分:)
【解决方案2】:

如果预期内容是使用拉丁脚本以某种语言编写的,则只需计算空值即可检测 UTF-16。在 UTF-8 中,空字节会解码为 NUL 控制字符,它们不会正常出现在文本中。

用其他脚本编写的语言不能在 UTF-16 和 UTF-8 中完全有效,除非它是人为构造的。

所以,首先自己检测它是否是完全有效的 UTF-8 序列:

  • 如果是,请检查空字节,如果有,则为 UTF-16。否则为 UTF-8。
  • 如果不是,则为 UTF-16。

如果上面的结果是 UTF-16,那还不够,因为您还必须知道字节序。对于用拉丁文字编写的语言,奇数或偶数字节的数量会说明这一点。

【讨论】:

  • 它不仅仅是拉丁文 - 它可以是任何语言的任何脚本(包括 RTL)
  • @AleksG 当然,这不是必需的。只是说,如果您希望文本在任何语言中都清晰易读,那么我在回答中所说的话实际上可以工作。 UTF-8 和 UTF-16 只是人工构造的字符串,在任何语言中都无法辨认。
  • “拉丁文”定义不明确;如果您的意思是 Latin-1,那甚至不包括像破折号这样的常用字符,
  • @larsmans 我的意思是拉丁脚本语言,如英语、芬兰语、德语、冰岛语等。当编码为 UTF-16 时,它们必然有空字节,因为它们主要使用前 256 个字符,基本和补充拉丁语。我根本不是指编码 ISO-8859-1。
猜你喜欢
  • 2014-01-05
  • 2013-09-30
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 2018-09-03
  • 2017-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多