C++ std::不能在Windows上使用UTF-8吗?

C++ std::不能在Windows上使用UTF-8吗?,c++,visual-c++,unicode,encoding,utf-8,C++,Visual C++,Unicode,Encoding,Utf 8,我想让std::cout打印一个UTF-8文本。对于gcc来说,这似乎是一项简单的任务,但是对于Windows来说,这是一项极其困难的任务 我正在尝试的代码是: std::cout << "Ελληνικά Русский 你好"; 下面是我要做的: 确保源文件是utf-8编码的,并且内容正确(在另一个编辑器中打开它们,检查标志符号和文件编码) 从公式中删除控制台——将输出重定向到文件,并使用utf-8感知编辑器检查其内容(与源代码相同) 将/utf-8 cmdline选项与MSV

我想让
std::cout
打印一个UTF-8文本。对于gcc来说,这似乎是一项简单的任务,但是对于Windows来说,这是一项极其困难的任务

我正在尝试的代码是:

std::cout << "Ελληνικά Русский 你好";
下面是我要做的:

  • 确保源文件是utf-8编码的,并且内容正确(在另一个编辑器中打开它们,检查标志符号和文件编码)

  • 从公式中删除控制台——将输出重定向到文件,并使用utf-8感知编辑器检查其内容(与源代码相同)

  • 将/utf-8 cmdline选项与MSVC2015+一起使用——这将强制编译器将所有源文件视为utf-8编码一次,并且存储在结果二进制文件中的字符串文本将进行utf-8编码

  • 从等式中删除iostreams(不能等到这个库死掉,tbh)——使用cstdio

  • 在这一点上,输出应该起作用(对我来说是这样的)

  • 要使控制台输出正常工作,请使用SetConsoleOutputCP(CP_UTF8),并使其使用支持Unicode平面的TrueType字体(我怀疑,要使汉字在控制台中工作,您需要在系统中安装支持相关Unicode平面的字体,并且您的控制台应配置为使用该字体)

  • 不确定控制台输入(从未处理过),但我怀疑SetConsoleCP(CP_UTF8)应该使它能够与非宽I/o一起工作

  • 放弃使用宽i/o(wcout/etc)的想法——无论如何,为什么要这样做?Unicode与utf-8编码的字符常量配合得很好*

  • 一旦您达到这个阶段,就是处理iostreams的时候了(如果您坚持使用它的话)。我暂时不考虑wcin/wcout。如果它们还不起作用——试着在相关的cin/cout中嵌入utf-8语言环境

  • 所提倡的思想是仅在进行Windows API调用时才转换为UCS-2。这使得您的OutputForwarderBuffer不必要

  • 我想(如果你真的坚持的话)现在你可以试着让广泛的iostreams发挥作用。祝您好运,我想您必须重新配置控制台(这将中断非宽I/o),或者以某种方式让您的wcout/wcin动态执行UCS2到UTF8的转换(并且仅当它连接到控制台时)

  • 编辑: 从Windows 10开始,您还需要:

    setvbuf(stderr, NULL, _IOFBF, 1024);    // on Windows 10+ we need buffering or console will get 1 byte at a time (screwing up utf-8 encoding)
    setvbuf(stdout, NULL, _IOFBF, 1024);
    

    不幸的是,这也意味着,如果在下一次刷新之前完全填充缓冲区,仍然有可能导致输出错误。正确的解决方案——在发送到输出的每个字符串之后(假设每个字符串小于1024),手动刷新它(
    endl
    fflush()
    )。如果MS支持行缓冲…

    您是否尝试使用
    wcout
    <代码>标准::wcout@AlgirdasPreidžius我知道它会起作用。我的目标是避免修改这一行代码,因为这一行代码在Linux上工作得非常好。您能更具体地说明哪些代码不工作吗?发生了什么?在Windows/MSVCRT上,
    std::cout
    无法支持Unicode,句号。(您可以接近代码页65001,但控制台中有无法克服的错误会破坏它,Microsoft已经永远忽略了它们,所以不要期望它们得到修复。)
    std::wcout
    可以通过使用
    \u setmode
    \u UTF8
    使其大部分工作,但仍然存在问题(这都是为了解决这个问题)并且你不能在之后使用与cout相关的接口,否则它会爆炸。你通常最好是(a)读取/发送UTF-8字符到控制台,而不管Windows用户是否看到mojibake,或者(b)仅使用您自己的输入/输出函数,在Windows上的Win32 WriteConsoleW等接口和其他平台上的标准库之间进行切换,在其他平台上,该接口的破坏程度较轻。但您(1)通过MSVCRT在控制台上显示正确的输出,以及(2)使用未更改的
    std::cout
    调用的要求是不可调和的。
    setvbuf(stderr, NULL, _IOFBF, 1024);    // on Windows 10+ we need buffering or console will get 1 byte at a time (screwing up utf-8 encoding)
    setvbuf(stdout, NULL, _IOFBF, 1024);