CP_UTF8 是 WriteConsoleA / WriteFile 的受支持代码页吗?

Is CP_UTF8 a supported codepage for WriteConsoleA / WriteFile?

many examples人建议使用与此类似的技巧来获取 Unicode 控制台输出:

begin
  OldConsoleOutputCP := GetConsoleOutputCP();
  SetConsoleOutputCP(CP_UTF8);
  try
    // Might also use WriteConsoleA, but this has drawbacks with output redirection
    WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), Utf8Bytes, ...);
  finally
    // We better restore the output CP that was in use before our program started!
    SetConsoleOutputCP(OldConsoleOutputCP);
  end;
end.

这似乎工作得很好。

控制台输出的 MSDN 文档 only ever mentions (at least to my knowledge) that you should use WriteConsoleW 和重定向输出的 WriteFile。 (可以通过GetConsoleMode的return值等类似方法检测句柄是否为控制台句柄)

是否微软正式支持使用SetConsoleOutputCP(CP_UT8)向控制台输出Unicode文本并重定向输出?如果是,它记录在哪里?

我认为 UTF-8 多字节代码页应该只用于 WideCharToMultiByteMultiByteToWideChar 函数?

Is it officially supported by Microsoft to use SetConsoleOutputCP(CP_UT8) to output Unicode text to the console and redirected output?

它当然没有得到明确支持,但在这里很难说什么才算是“支持”——这是一个文档很差甚至完全缺失的领域。

实际上 I/O 存在严重错误,包括 WriteFile,当控制台在另一端并且其代码页设置为 65001 时。一般来说,Win32 I/O API(以及建立在它们之上的 MSVCRT stdlib 例程)通过返回实际上是字符数的字节数写入或读取计数而失败。

这在您的示例中无关紧要,因为您忽略了 WriteFilelpNumberOfBytesWritten outparam,但通常当您使用非 ASCII 字符时,错误的计数将导致错误的重复尝试读取输入时输出并挂起等待更多数据。

这是控制台 (conhost) 中的错误:对于用作默认代码的双字节字符集代码页,它具有特殊情况支持,可以将正确的计数传回 Windows任何安装区域设置的页面(“非 Unicode 应用程序的语言”),但不适用于其他通用多字节编码。

正如@IInspectable 所言linked,微软至少有一部分明确拒绝修复此问题的一个明显方面,尽管根本原因不是微软的那部分。无论哪种方式,令人遗憾的是,这个长期存在且令人深感沮丧的问题似乎不会很快结束。

// Might also use WriteConsoleA, but this has drawbacks with output redirection

是的,一种常见的方法是自己检测 stdout 是否是控制台(例如,使用 _isatty)并在这种情况下分支到 WriteConsoleW