确定字节数组是不是包含 ANSI 或 Unicode 字符串?

Posted

技术标签:

【中文标题】确定字节数组是不是包含 ANSI 或 Unicode 字符串?【英文标题】:Determine if a byte array contains an ANSI or Unicode string?确定字节数组是否包含 ANSI 或 Unicode 字符串? 【发布时间】:2011-10-03 21:28:33 【问题描述】:

假设我有一个接收字节数组的函数:

void fcn(byte* data)

...

有人知道 fcn() 确定 data 是 ANSI 字符串还是 Unicode 字符串的可靠方法吗?

请注意,我故意不传递长度参数,我收到的只是指向数组的指针。长度 arg 会很有帮助,但我没有收到它,所以我必须不用它。

这篇文章提到了一个显然可以做到的 OLE API,但他们当然不会告诉你哪个 api 函数:http://support.microsoft.com/kb/138142

【问题讨论】:

没有可靠的方式,但IsTextUnicode可能就是这个意思。 你知道它包含一个非零长度的字符串吗?您是否知道读取几个字节通过刺尾的事实并不致命?我认为答案显然是不存在任何可靠的方法。有些字符串既是有效的 ASCII 也是有效的 Unicode。 请参阅 en.wikipedia.org/wiki/Bush_hid_the_facts 了解如何出错的有趣示例。 为什么调用者不告诉你它是什么类型的字符串?在创建字符串时,该信息肯定存在或存在。为什么不能重新设计函数,让调用者告诉你它是什么? @Joey:我明白了。 Windows-1252 通常错误地被称为“ANSI”,尽管它从来都不是 ANSI 标准。它是 ISO 8859-1 的超集,也称为 Latin-1。 【参考方案1】:

首先,关于术语。没有像 ANSI 字符串这样的东西。有 ASCII 字符串,代表一种字符编码。 ASCII 由 ANSI 开发,但它们不可互换。

此外,没有 Unicode 字符串这样的东西。有Unicode encodings,但这些只是Unicode本身的一部分。

我假设“Unicode 字符串”是指“UTF-8 编码的代码点序列”。对于 ANSI 字符串,我假设您的意思是 ASCII。

如果是这样,那么根据 UTF-8 编码的定义,每个 ASCII 字符串也是一个 UTF-8 字符串。 ASCII 只定义了 0x7F 以内的字符,所有 0x7F 以内的 UTF-8 代码单元(字节)的含义与它们在 ASCII 下的含义相同。

因此,您关心的是其他 128 个可能的值。那是……很复杂。

您会问这个问题的唯一原因是您是否无法控制字符串输入的编码。因此,问题在于 ASCII 和 UTF-8 不是唯一可能的选择。

例如,Latin-1。有许多用 Latin-1 编码的字符串,它占用 ASCII 不使用的其他 128 个字节并为它们定义字符。这很糟糕,因为其他 128 个字节会与 UTF-8 的编码冲突。

还有code pages。许多字符串是针对特定代码页进行编码的;在 Windows 上尤其如此。解码它们需要知道您正在处理的代码页。

如果您处于确定字符串是 ASCII(7 位,高位始终为 0)或 UTF-8 的情况,那么您可以轻松做出判断.字符串是 ASCII(因此也是 UTF-8),或者一个或多个字节的高位设置为 1。在这种情况下,您必须使用 UTF-8 decoding logic。

除非您真的确定这些是唯一的可能性,否则您将需要做更多的事情。您可以通过尝试通过 UTF-8 解码器运行数据来验证数据。如果它遇到无效的代码单元序列,那么您就知道它不是 UTF-8。问题是理论上可以创建一个在技术上是有效的 UTF-8 的 Latin-1 字符串。那个时候你有点搞砸了。基于代码页的字符串也是如此。

最终,如果您不知道字符串的编码是什么,则无法保证您可以正确显示它。这就是为什么重要的是要知道你的字符串来自哪里以及它们的含义。

【讨论】:

对于字节数组,ANSI通常指任何非ASCII的多字节编码,其字符值大于127,依赖于代码页,Unicode通常指@987654327 @超过UTF-8. @RemyLebeau-TeamB:鼓励人们将 UTF-16 称为“Unicode”是一种可怕的做法,绝不应该这样做。如果您正在谈论您拥有byte* 的“字符串”,这将变为 double 我不是在鼓励任何事情,我只是指出我在实践中观察到的情况。 是的,使用“Unicode”来表示 UTF-16LE 编码是不幸且令人困惑的,但它是 Microsoft 世界的标准术语(同样具有误导性的“ANSI”也是如此),所以我们没有选择,但要处理它。这源于微软早期的 Unicode 实现,当时人们认为 UCS-2 是任何人与 Unicode 字符串交互的唯一方式。由于 Windows 对 UTF-8 的二级支持,这个错误一直存在。 我注意到在 Linux 和网络世界中使用“Unicode”作为 UTF-8 的相同趋势。这和 Windows 术语一样错误。

以上是关于确定字节数组是不是包含 ANSI 或 Unicode 字符串?的主要内容,如果未能解决你的问题,请参考以下文章

编码(ACSII unicod UTF-8)QT输出中文乱码深入分析

确定数组是不是包含重复值的最快方法是啥?

如何检查字节数组是否包含Java中的Unicode字符串?

确定文件是不是存在或为 0 字节

byte怎么转换为char

多字符集(ANSI)和UNICODE及字符串处理方式准则