4

我知道加载 unicode 有点费力,但我看不出如何将提供给其他人的解决方案应用于我的特定问题。

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

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

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

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 吗?有没有办法确保这一点?我只需要确保我有一个宽字符串,其中包含文本编辑器中显示的文本。

非常感激地收到任何帮助。

4

3 回答 3

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

于 2011-08-15T14:37:39.957 回答
3

DrawTextW 期待 UTF-16。

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

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

于 2011-08-15T14:54:25.197 回答
-1

从来不理解那里宣布的关于在任何地方都使用 UTF-8 的想法,自己实现必要的功能(你也可以为 UTF-16 做同样的事情),然后在与 Windows API 通信时将其转换回 UTF-16(并且没有知道这应该如何避免 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 我都认为自己很幸运) - 也使意图更加清晰。

于 2011-08-15T15:06:37.307 回答