在C ++流中使用UTF-8的正确和跨平台方式

时间:2014-05-10 17:23:31

标签: c++ utf-8 stl iostream

据我所知this answer to the similar question,Visual C ++ STL实现中有still unfixed bug。 因此,不可能只编写std::cout << raw_utf8_string << std::endl并在Windows下享受漂亮的UTF-8字符;(

注意:我的测试程序存在here

但也许有一个非常简单易懂的解决方法来处理这个问题? 我的thoghts:创建一个类似cout_ex的包装类,它将使用Windows API WriteConsoleA 用于控制台输出。
在其构造函数中this

#ifdef _WIN32
if (IsValidCodePage (CP_UTF8))
{
    if (!SetConsoleCP (CP_UTF8))
        std::cout << "Could not set console input code page to UTF-8" << std::endl;
    if (!SetConsoleOutputCP (CP_UTF8))
        std::cout << "Could not set console output code page to UTF-8" << std::endl;
}
else
    std::cout << "UTF-8 code page is not supported in your system" <<   std::endl;
#endif

在输出方法中执行以下操作:

char const raw_utf8_text[] = "Blåbærsyltetøy! кошка!";

DWORD raw_written = 0;
WriteConsoleA (GetStdHandle (STD_OUTPUT_HANDLE), raw_utf8_text, std::strlen (raw_utf8_text), &raw_written, NULL);

并且不要忘记在src的最开始使用未记录的Visual C ++编译指示:

#pragma execution_character_set("utf-8")

但也许有一个更清晰的解决方案:)即使使用像Poco / Boost /等一些外部库。

我尝试阅读那些文章12,但我发现这种方式太复杂了。 附:覆盖的流类也应该将控制台字体设置为Unicode字体 P.P.S.软件版本:Windows 8 x64 + Visual C ++ 2013 Express。

1 个答案:

答案 0 :(得分:1)

您应该在输出流中灌输正确的codecvt_facet。

std::locale loc;
string encoding=getOutputEncoding(); // 
loc=std::locale(loc, createCodecvt(encoding));
cout.imbue(loc);
cout.rdbuf().imbue(loc);

Complete code here

此方面应将内部编码转换为外部编码。由于STL实现中some bugs,如果内部存储格式采用单字节或多字节编码,则可能无法执行此操作。有一种解决方法 - 使用filestreambuf而不是默认输出缓冲区。

您可能必须实施自己的codecvt_facet或使用我的iconv wrapper

总的来说,我仍然建议使用宽字符进行内部处理。这样您甚至可以避免任何额外的转换(除了系统默认转换)。