对C ++的std :: wstring,UTF-16,UTF-8以及在Windows GUI中显示字符串感到困惑

时间:2010-03-27 00:53:07

标签: c++ unicode utf-8 utf-16 wstring

我正在为Windows开发一个仅限英语的C ++程序,我们被告知“总是使用std :: wstring”,但似乎团队中的任何人都没有太多理解。

我已经阅读了标题为"std::wstring VS std::string的问题。这非常有帮助,但我仍然不太明白如何将所有这些信息应用到我的问题中。

我正在处理的程序在Windows GUI中显示数据。该数据以XML格式保存。我们经常使用XSLT将XML转换为HTML或XSL:FO用于报告目的。

根据我所读到的内容,我的感觉是HTML应编码为UTF-8。我对GUI开发知之甚少,但我读到的一点点表明GUI内容都是基于UTF-16编码的字符串。

我试图了解这让我失望的地方。假设我们认为所有持久化数据都应该是UTF-8编码的XML。这是否意味着为了在UI组件中显示持久化数据,我应该真正执行某种明确的UTF-8到UTF-16转码过程吗?

我怀疑我的解释可以使用澄清,所以如果您有任何问题,我会尝试提供。

5 个答案:

答案 0 :(得分:8)

从NT4开始的Windows基于Unicode编码的字符串,是的。早期版本基于UCS-2,它是UTF-16的前身,因此不支持UTF-16所做的所有字符。更高版本基于UTF-16。但并非所有操作系统都基于UTF-16 / UCS-2。例如,* nix系统基于UTF-8。

UTF-8是持久存储数据的理想选择。它是所有Unicode环境中普遍支持的编码,它在数据大小和无损数据兼容性之间取得了良好的平衡。

是的,您必须解析XML,从中提取必要的信息,然后将其解码并转换为UI可以使用的内容。

答案 1 :(得分:5)

AFAIK当您在Windows上使用std :: wstring在C ++中使用UTF-8存储在文件中时(这听起来不错且合理),然后您必须在写入文件时将数据转换为UTF-8,并且从文件读取时转换回UTF-16。请查看此链接:Writing UTF-8 Files in C++

我会坚持Visual Studio默认的项目 - >属性 - >配置属性 - >一般 - >字符集 - >使用Unicode字符集,使用wchar_t类型(即使用std :: wstring)和使用TCHAR类型。 (例如,我只使用wlenlen版本的strlen和 _tcslen。)

答案 2 :(得分:4)

std :: wstring在技术上是UCS-2:每个字符使用两个字节,代码表主要映射到Unicode格式。 重要的是要理解UCS-2与UTF-16不同! UTF-16允许“代理对”以表示超出双字节范围的字符,但是UCS- 2对每个字符,句点使用恰好两个字节。

您的情况的最佳规则是在读取和写入磁盘时进行转码。一旦它在内存中,请保持UCS-2格式。 Windows API会将其读作好像是UTF-16(也就是说,当std :: wstring不理解代理对的概念时,如果你手动创建它们(如果你唯一的语言是英语),Windows会读它们。

每当您在现代读取数据格式(如XML)时,您可能需要进行转码。这是生活中令人不快和非常不幸的事实,但不可避免,因为Unicode是一种可变宽度的字符编码,C ++中大多数基于字符的操作都是以数组形式完成的,你需要一致的间距。

高级框架(如.NET)掩盖了大部分细节,但在幕后,他们以相同的方式处理转码:将可变宽度数据更改为固定宽度字符串,操纵它们,以及然后在输出需要时将它们改回可变宽度编码。

答案 3 :(得分:3)

在Windows上使用std :: wstring用于GUI相关字符串的一个好处是,内部所有Windows API调用都使用和操作UTF-16。如果您注意到所有Win32 API调用的2个版本都采用字符串参数。例如,“MessageBoxA”和“MessageBoxW”。这两个定义都存在,实际上您可以调用任何一个,但如果启用了Unicode支持,则会发生以下情况:

#define MessageBox MessageBoxW

然后,您将进入TCHAR和其他Microsoft技巧,尝试更轻松地处理同时具有ANSI和Unicode版本的API。简而言之,您可以调用基于Unicode的Windows内核,但如果您不使用宽字符版本,则需要为接受Win32 API调用的每个字符串转换为Unicode的成本。< / p>

UTF-16 and Windows kernel use

答案 4 :(得分:1)

即使您说您的数据中只有英文,您可能也错了。由于我们现在处于一个全球化的世界,名字/地址/等等都有外国字符。好的,我不知道你有什么类型的数据,但通常我会建立你的应用程序以支持UNICODE来存储数据和向用户显示数据。这将建议在执行GUI时使用带有UTF-8的XML来存储和UNICODE版本的Windows调用。由于Windows GUI使用UTF-16,其中每个令牌都是16位,我建议将数据存储在16位宽的字符串中。我猜你的windows编译器会将std :: wstring作为16位用于此目的。

那么你必须在UTF-16和UTF-8之间进行大量的转换。对某些现有库执行此操作,例如ICU