当VS启动程序时,WriteFile行为会有所不同

时间:2014-02-20 22:38:28

标签: c++ winapi console visual-studio-2013

我正在尝试将UTF8字符串写入stdout - 并在控制台中正确显示它们。

为实现此目的,我使用SetConsoleOutputCP(CP_UTF8)并使用WriteFile编写数据。结果如预期,我的字符串正确显示。只有在检查实际写入的字节数时才会出现问题:从正常的命令控制台调用时,无论stdout是否被重定向,它都将正确计算字节数。从VS2013启动时,它会报告编写字符的数量。

显然,不知道实际写入了多少字节会使这种方法变得无用。

我想知道的是:

  • 这有什么合理的解释吗?看来这应该是一个bug?
  • 我可以在这里使用简单的修复/解决方法吗?

显示所描述行为的简短示例程序:

#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,但是如果可能的话我想绕过它。

1 个答案:

答案 0 :(得分:2)

不同之处在于控制台设置。默认VS调试控制台使用不能正确呈现文本的光栅字体。您可能已将个人控制台设置为使用Lucida,这会使文本正常并返回写入的7个字节。如果您更改VS控制台以使用相同的结果,则会得到相同的结果。