使用UTF-8输出在Windows控制台下printf和std :: ostream之间有什么不同

Art*_*yom 7 c++ unicode winapi visual-c++

我有一个程序将UTF-8字符串打印到控制台:

#include <stdio.h>

int main()
{
    printf("??? Peace ??????\n");
    return 0;   
}
Run Code Online (Sandbox Code Playgroud)

我将控制台配置为使用True Type字体(Lucida Console),定义UTF-8代码页(chcp 65001)使用MinGW GCC和Visual Studio 2010编译此程序它完美地工作,我看到:输出:

??? Peace ??????
Run Code Online (Sandbox Code Playgroud)

我也这样做 std::cout

#include <iostream>

int main()
{
    std::cout << "??? Peace ??????\n" ;
    return 0;   
}
Run Code Online (Sandbox Code Playgroud)

如上所述,使用MinGW GCC完全正常,但使用Visual Studio 2010,我得到正方形,而不是正方形(每个非ASCII字母两个).

如果我使用重定向运行程序,test >test.txt我会在文件中获得完美的UTF-8输出.

两个测试都在Windows 7上完成.

问题:

  1. Visual Studio标准库中printf和std :: cout在处理输出流时有什么区别 - 显然其中一个有效,另一个没有?
  2. 怎么解决这个问题?

真正的答案:

简而言之:你被搞砸了 - std::cout与MSVC + UTF-8无法真正合作 - 或者至少需要付出巨大努力才能使其表现得相当合理.

总之:阅读答案中引用的两篇文章.

Che*_*Alf 1

您有许多有缺陷的假设,让我先纠正这些假设:

  • 看起来可以与 g++ 一起工作并不意味着 g++ 可以正常工作。

  • Visual Studio 不是一个编译器,它是一个支持多种语言和编译器的 IDE。

  • Visual C++ 标准库需要修复的结论是正确的,但导致该结论的推理是错误的。g++ 标准库也需要修复。更不用说g++编译器本身了。

现在,Visual C++ 将 Windows ANSI(API 函数指定的编码)GetACP作为其未记录的 C++ 执行字符集。即使您的源代码是带有 BOM 的 UTF-8,窄字符串最终也会转换为 Windows ANSI。如果编译时在您的计算机上是一个包含所有非 ASCII 字符的代码页,那么就可以了,但否则窄字符串将会出现乱码。因此,如果不提及源代码编码和 Windows ANSI 代码页,测试结果的描述就严重不完整。

但无论如何,“如果我使用重定向运行程序,test >test.txt我会在文件中得到完美的 UTF-8 输出”表明您面临的是来自 Visual C++ 运行时的一些 C++ 级别帮助,它绕过了流输出并使用直接控制台输出以便在控制台窗口中显示正确的字符。

当其假设(例如 Windows ANSI 编码的窄字符串文字)不成立时,此帮助会导致垃圾。

这也意味着当您重定向流时,效果会神秘地消失。然后,运行时库检测到流转到文件,并关闭直接控制台输出功能。您不能保证获得原始的原始字节值,但显然您做到了,这是运气不好,因为它掩盖了问题。

顺便说一句,Windows 控制台中的代码页 65001 在实际中不可用。许多程序就崩溃了。包括例如more


获得正确输出的一种方法是直接使用 Windows API 级别,通过直接控制台输出。

使用 C++ 流获得正确的输出要复杂得多。

它是如此复杂,以至于这里没有空间(正确地!)描述它,所以我必须转而向您推荐我关于它的由两部分组成的博客文章系列:第 1部分第 2 部分

  • 因为这不是真正期望的事情。最后我找到了您的(第 2 部分)文章、这篇 http://blogs.msdn.com/b/michkap/archive/2008/03/18/8306597.aspx Kaplan 的文章和这个错误报告 http://connect.microsoft。 com/VisualStudio/feedback/details/431244/std-ostream-fails-to-write-utf-8-encoded-string-to-console 。最后,唯一合理的“解决方案”是创建我自己的流缓冲区。这是另一个关于完全糟糕的 Windows Unicode 模型的例子,其中 1/2 的应用程序不能很好地处理 Unicode。 (2认同)