【发布时间】:2014-06-28 08:20:24
【问题描述】:
我从this answer to the similar question 了解到,Visual C++ STL 实现中有一个still unfixed bug。
因此,不可能只写std::cout << raw_utf8_string << std::endl 并在 Windows 下享受漂亮的 UTF-8 字符;(
注意:我的测试程序是 here。
但也许有一个非常简单易懂的解决方法来处理这个问题?
我的想法:制作一个像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:
#pragma execution_character_set("utf-8")
但也许有一个更清晰的解决方案 :) 即使使用一些外部库,如 Poco/Boost/等。
我尝试阅读那些文章1,2,但我发现这种方式太复杂了。
附言重写的流类也应该将控制台字体设置为 Unicode 字体。
附言软件版本:Windows 8 x64 + Visual C++ 2013 Express。
【问题讨论】:
-
我没有深入检查
SetConsoleCP,但一般的口头禅是在 Windows 上 UTF-8 不是受支持的 CP(CP_UTF8主要用于MultiByteToWideChar和WideCharToMultiByte)。在 Windows 上使用 UTF-8 的典型方式是在 API 边界处转换为WCHAR。 -
您可能会更幸运地将控制台 CP 设置为 CP_UNICODE,然后手动将 UTF-8 转换为 UTF-16(请记住 CP_UNICODE==UTF-16)。
-
@MatteoItalia 所以在 Windows 下我只能转换为 UTF-16 并使用 std::wcout 进行输出?
-
@rodrigo 我会检查这个。但是,Unicode != UTF-16 :) 为什么微软这么认为,我不明白...
-
@Axilles:我知道,这就是为什么我说
CP_UNICODE,而不是Unicode。更奇怪的是为什么他们认为 ANSI 等于......有用的东西。