将 UTF-16(Windows 上的 wchar_t)转换为 UTF32

Posted

技术标签:

【中文标题】将 UTF-16(Windows 上的 wchar_t)转换为 UTF32【英文标题】:Convert UTF-16 (wchar_t on Windows) to UTF32 【发布时间】:2016-02-24 22:21:20 【问题描述】:

我有一个由 Windows API 函数(带有 LOCALE_SLONGDATE 的 GetLocaleInfoEx)作为 wchar_t 提供给我的字符串。说从 Windows 返回的值将是 UTF-16 是否正确,因此它可能不是一个 wchar_t,一个“可打印字符”?

为了使我的解析器更容易编写,是否有一个函数可以用来从 UTF-16 转换为 UTF-32,我可以保证(我假设)一个数组元素代表一个字符?

【问题讨论】:

通过查找和组合代理对自行执行转换。或者使用像 iconv 这样的库。 即使使用 UTF-32,您仍可能需要以某种方式处理组合标记。 我一直不清楚与 UCS-2 相比,Windows 对 UTF-16 的支持程度如何。 Unicode 是基于排版人员的选择。谁是非常明智的人,当你在铅块周围走动时,你必须是谋生的。日期字符串经常出现在印刷文本中,它们的字形每个只占一个前导块。您必须处理无法在旧代码页或 Unicode 版本 1 中表示或需要组合字符的字形的可能性为零。 我相信可以自定义语言环境,因此您绝对可以得到任何东西。但出于同样的原因,即使我们不担心 Unicode,也无法合理地解析它们。您实际上想在这里实现什么目标? 【参考方案1】:

在哪里可以保证(我假设),一个数组元素代表一个字符?

这不是 Unicode 的工作方式。一个代码点(UTF-32 中的数组元素)不一定映射到单个可见字符。由于 Unicode 组合字符等功能,多个代码点可以组合形成一个字符。

如果你想知道一个 Unicode 字符串有多少个可见字符,你必须做真正的 Unicode 分析。

即使有日期(特别是您要求的长格式日期),您也不能安全地使用这些功能。语言环境可以返回任意 Unicode 字符串,因此您无法仅从代码点的数量知道 Unicode 字符串的长度。

【讨论】:

谢谢尼科尔。这是相当令人失望的。那么,比如 GDI+ 中的字符串渲染函数也都考虑到了这一点? GDI+ 可能(我不确定,但我会这么认为); DirectWrite 是的。这通常被统称为“Unicode 整形”;在 Windows 上,低级 Uniscribe 库直接执行此操作(但请注意,使用起来非常复杂)。【参考方案2】:

查看documentation for LOCALE_SLONGDATE 表示除格式图片以外的任何字符都必须用单引号引起来。所以在这种特殊情况下转换为 UTF-32 确实可以解决您的问题(但请参阅下面的附带条件)。

同样,您也不需要这样做。唯一不代表单个 UTF-32 字符的 UTF-16 字符是代理字符,它们都不会被误认为是单引号。所以要从周围的文本中分离出格式图片,你只需要扫描 UTF-16 字符串中的单引号。 (UTF-8 也是如此;唯一看起来像单引号的字节单引号。)

任何代理对、组合字符或其他复杂情况都应始终安全地隐藏在由此分隔的子字符串中。如果您从不尝试细分子字符串本身,那么您应该是安全的。


附带条件:文档没有说明是否允许在语言环境中将单引号与组合字符组合在一起,如果可以,将如何解释。我将其解释为不允许允许这样的组合。无论如何,Windows 本身似乎不太可能费心处理这种不必要的复杂问题。因此,忽略这种情况也应该足够安全,但是 YMMV。

【讨论】:

有趣。谢谢哈利。

以上是关于将 UTF-16(Windows 上的 wchar_t)转换为 UTF32的主要内容,如果未能解决你的问题,请参考以下文章

wchar_t 和编码

在 Windows 和 Linux 下,在 C 中将 UTF-16 转换为 UTF-8

如何读取 UTF-16 文件并将其内容与使用十六进制值定义的 wchar_t* 字符串文字进行比较

C++ 标准是不是要求对 wchar_t 进行编码?

在wstring到str转换的CPP问题

将 unicode 代码点转换为 utf-16