繁体   English   中英

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

[英]Confused about C++'s std::wstring, UTF-16, UTF-8 and displaying strings in a windows GUI

我正在为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转码过程吗?

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

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

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

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

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)掩盖了大部分细节,但在幕后,他们以相同的方式处理转码:将可变宽度数据更改为固定宽度字符串,操纵它们,然后更改它们当输出需要时,返回到可变宽度编码。

AFAIK在Windows上使用std :: wstring在C ++中工作并使用UTF-8存储在文件中(这听起来很合理),然后你必须在写入文件时将数据转换为UTF-8,然后转换回从文件读取时的UTF-16。 看看这个链接: 用C ++编写UTF-8文件

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

在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。

UTF-16和Windows内核使用

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

那么你必须在UTF-16和UTF-8之间进行大量的转换。 用一些现有的库来做,比如ICU

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM