在c ++文件加载期间UTF8加扰

时间:2011-08-15 14:25:16

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

我知道加载unicode是一个有点劳累的观点,但我看不出如何将呈现给别人的解决方案应用到我的特定问题中。

我有一个Win7 / C ++ / DirectX9 GUI库,可以将文本呈现到屏幕上。我之前从未遇到任何问题,因为它只能用于西欧语言。现在我必须和匈牙利人一起使用它,这让我很头疼!我的特殊问题是加载那种语言中的特殊字符。

举个例子,FELNŐTTEKNEK,意思是ADULT。

如果我将此字符串硬编码到我的应用程序中,它会正确呈现:

guiTitle->SetText( L"FELNŐTTEKNEK" );

这将字符串存储为std :: wstring,使用ID3DXFont :: DrawTextW()呈现它。它还证明了我选择的字体Futura CE能够渲染特殊字符(CE =中欧)。

到目前为止一切顺利。接下来,我只是希望能够从文本文件加载文本。没什么大不了。但结果很糟糕!特殊Ő被另一个字符取代,主要是Å甚至两个字符,如Å(第二个通常是不可打印的)

我确保通过输入文本文件编码为UTF-8并且天真地尝试加载它:

wifstream f("data/language.ini");
wstring w;  
getline( f, w );    
guiTitle->SetText( w );

不知怎的,我仍在争先恐后。我加载为UTF-8吗?有没有办法确保这个?我只需要确保我在文本编辑器中显示带有文本的宽字符串。

最感激的任何帮助。

的Si

3 个答案:

答案 0 :(得分:7)

忘记wifstream,要让它发挥作用太难了。做:

ifstream f(L"data/language.ini");
string str;  
getline( f, str );
guiTitle->SetText( utf8_to_utf16(str).c_str() );

并使用MultiByteToWideChar来实施utf8_to_utf16

另见https://stackoverflow.com/questions/1049947/should-utf-16-be-considered-harmful

答案 1 :(得分:3)

DrawTextW期待UTF-16。

您正在做的是将每个UTF-8代码单元(字节)转换为16位值,并将其填充为零 - 只有当您的UTF-8仅包含来自的UTF-8时,才能正确地将UTF-8转换为UTF-16 ascii unicode的子集。

您需要做的是正确地从UTF-8转换为UTF-16。将字符串加载到std :: string(而不是std :: wstring),然后将该UTF-8字符串转换为UTF-16字符串,并将其传递给期望UTF-16字符串的API。

答案 2 :(得分:-1)

永远不了解{@ 3}}关于在任何地方使用UTF-8,自己实现必要的功能(也可以为UTF-16做)的想法,然后在沟通时将其转换回UTF-16使用Windows API(并且不知道应该如何避免Windows API中的问题 - 毕竟你仍然给它UTF-16字符,因此无论如何都会遇到所有相同的错误),似乎有很多额外的工作没有任何好处。

无论如何,而不是“使用std :: string,然后使用低级方法将其转换为UTF-16”,你可以让API完成它的工作(注意这可能不会带来最好的性能,Ray Chen有一些系列关于那条路 - 虽然我希望新的编译器能够解决这个问题以及一个几乎不重要的普通文件。

基本上你可以这样做:

 std::wifstream src;
 src.imbue(std::locale("UTF-8")); // use correct encoding.
 src.open(file);

为什么所有的工作都是你自己(并且每次我都不必使用MultiByteToWideChar,我认为自己很幸运)如果图书馆也可以这样做 - 也会使意图更加清晰。