我正在尝试将UTF8字符串写入stdout - 并在控制台中正确显示它们。
为实现此目的,我使用SetConsoleOutputCP(CP_UTF8)
并使用WriteFile
编写数据。结果如预期,我的字符串正确显示。只有在检查实际写入的字节数时才会出现问题:从正常的命令控制台调用时,无论stdout是否被重定向,它都将正确计算字节数。从VS2013启动时,它会报告编写字符的数量。
显然,不知道实际写入了多少字节会使这种方法变得无用。
我想知道的是:
显示所描述行为的简短示例程序:
#include <stdio.h>
#include <Windows.h>
int wmain(int, wchar_t const**)
{
UINT oldcp = GetConsoleOutputCP();
if (!SetConsoleOutputCP(CP_UTF8))
{
fprintf(stderr, "setting cp failed\n");
return EXIT_FAILURE;
}
unsigned char utf8data[] = { 'H', 0xc3, 0xa4, 'l', 'l', 0xc3, 0xb6, '!', '\n', 0x00 };
DWORD size = (DWORD)(sizeof(utf8data) / sizeof(*utf8data)) - 1;
fprintf(stderr, "bytes in data: %d\n", size);
DWORD written = 0;
BOOL success = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), utf8data, size, &written, nullptr);
if (!success)
{
fprintf(stderr, "WriteFile failed\n");
return EXIT_FAILURE;
}
fprintf(stderr, "bytes written: %d\n", written);
SetConsoleOutputCP(oldcp);
return EXIT_SUCCESS;
}
调用consoleutf8.exe
时的输出:
bytes in data: 9
Hällö!
bytes written: 9
调用consoleutf8.exe > out.txt
时的输出(out.txt
包含正确的9个字节):
bytes in data: 9
bytes written: 9
从VS调用时的输出(ctrl + f5或f5无关紧要,不调试/释放):
bytes in data: 9
Hällö!
bytes written: 7
P.S。:我知道我可以检测是否连接了控制台,然后在我的数据的UCS2编码版本上使用WriteConsoleW
,但是如果可能的话我想绕过它。
答案 0 :(得分:2)
不同之处在于控制台设置。默认VS调试控制台使用不能正确呈现文本的光栅字体。您可能已将个人控制台设置为使用Lucida,这会使文本正常并返回写入的7个字节。如果您更改VS控制台以使用相同的结果,则会得到相同的结果。