在C++中有没有一种方法可以检查字符串是否包含Unicode字符?

3

有没有办法在C++中检查字符串是否包含Unicode字符?

我有一个字符串,需要验证它是否包含Unicode(UTF-8或UTF-16)字符。如果是,我需要将它们转换为ASCII。我对转换逻辑有一些想法,但需要帮助检测字符串中的Unicode字符。


2
你可以使用正则表达式。 - deW1
3
很抱歉打扰大家的兴致,但是要可靠地确定数据编码是完全不可能的。每个“解决方案”都是基于猜测(通过一些语言中的字节和字符的百分比、甚至是单词识别等等)。 - deviantfan
@EdChum 一般情况下,文件不需要 BOM,为什么要添加呢?而且在几乎所有的单字节字符集中,BOM 也是有效的。 - deviantfan
@deviantfan BOM 在 UTF16 中更或多或少是常规的;在 UTF-8 中并不那么频繁(虽然我见过)。而且,尽管 UTF-8 BOM 可以是合法的 ISO 8859-1(例如),但它对应的字符序列是 ï«¿,不太可能是文件的开头。 - James Kanze
@deviantfan 是的。如果文件是EBCDIC格式,那会更加混乱。猜测结果的可靠性在某种程度上取决于文件的来源。 (如果它是由Windows或Unix机器生成的,它就不会是EBCDIC:-)。) 大多数情况下,使用Unicode的文件将包含一些本地语言文本或相关内容,而不是随机字符。很难想象一个文件的上下文开头是 ï«¿;在这种情况下,我的 "不太可能" 是一种轻描淡写的说法;我想不到这种情况下它会以这种方式开始。 - James Kanze
显示剩余6条评论
2个回答

3
没有100%的保证解决方案。我会从读取文件的前100个字节开始,并尝试确定编码:
  • 如果文件以三字节序列0xEF、0xBB、0xBF开头,那么它很可能是UTF-8编码。在这种情况下,请删除这三个字节,并将剩余部分视为UTF-8进行处理(见下文)。

  • 如果文件以两个字节序列0xFE、0xFF开头,则可能是UTF16BE编码。请删除这两个字节,并将剩余部分视为UTF16BE进行处理(见下文)。

  • 如果文件以两个字节序列0xFF、0xFE开头,则可能是UTF16LE编码。请删除这两个字节,并将剩余部分视为UTF16LE进行处理(见下文)。

  • 如果文件中每隔一个字节(从第一个字节开始)大多数都为0,则该文件很可能是UTF16BE编码。(“大多数”数量不定,取决于数据来源,甚至只有几个也足够了)。请将其作为UTF16BE进行处理(见下文)。

  • 如果文件中每隔一个字节(从第二个字节开始)大多数都为0,则很可能是UTF16LE编码(在Windows世界中非常常见)。

  • 否则,这将是任何人的猜测,但将其视为UTF-8进行处理(不删除任何字节)可能是可以接受的。

至于如何处理文件:

  • 对于UTF-8编码,只需检查所有剩余字节是否在范围[0,128)内。如果不在,则该文件无法转换为ASCII;如果是,则该文件既是ASCII,也是UTF-8。对于大多数单字节编码,例如所有ISO-8859编码(仍然广泛使用),这也是有效的。

  • 对于UTF16BE编码,每隔一个字节(从第一个字节开始)应为0,而其他剩余字节应在范围[0,128)内。如果不在,则该文件无法转换为ASCII;如果是,则取每隔一个字节(从第二个字节开始)。

  • 对于UTF16LE编码,每隔一个字节(从第二个字节开始)应为0,而其他剩余字节应在范围[0,128)内。如果不在,则该文件无法转换为ASCII;如果是,则取每隔一个字节(从第一个字节开始)。

在所有情况下,在第一步删除任何字节后开始此处理过程。

最后,您没有说明您正在尝试做什么。有编码约定可以在纯ASCII中表示所有Unicode字符;如果您生成的ASCII将由期望其中一种约定的代码处理,则必须处理完整的Unicode(包括UTF-16中的代理对)并将Unicode转换为目标程序所期望的任何编码。例如,C++期望通用字符名称;例如,é的表示形式将是\u00E9。这意味着您还必须将\转换为\\。(据我所知,这种约定仅适用于像C、C++和Java这样的编程语言。)


2

无法一概而论。

字符串只是字符的序列(可以是任意大小)。与这种序列密不可分的编码将文本含义附加到字符串上。

在Windows中使用的编码是UTF-16,它允许您进行尝试。它提供了API函数IsTextUnicode,可以帮助您。但请注意,不能保证它会起作用。


(为避免混淆,顺便说一句:Windows 在许多地方使用 UTF16,但这并不意味着 Windows 上的每个程序和文件都是 UTF16) - deviantfan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接