【问题标题】:Is CP_UTF8 a supported codepage for WriteConsoleA / WriteFile?CP_UTF8 是 WriteConsoleA / WriteFile 支持的代码页吗?
【发布时间】:2016-10-12 10:37:10
【问题描述】:

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(至少据我所知)您 should use WriteConsoleW 用于控制台输出,WriteFile 用于重定向输出。 (可以通过GetConsoleMode的返回值等方法检测句柄是否为控制台句柄)。

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

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

【问题讨论】:

标签: delphi winapi unicode console delphi-xe7


【解决方案1】:

微软官方是否支持使用 SetConsoleOutputCP(CP_UT8) 将 Unicode 文本输出到控制台并重定向输出?

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

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

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

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

作为@IInspectable 的linked,至少微软的一部分已经明确拒绝修复这个问题的一个明显方面,尽管不是微软的那一点拥有根本原因。无论哪种方式,可悲的是,这个长期存在且令人深感沮丧的问题似乎不会很快结束。

// 也可以使用 WriteConsoleA,但这在输出重定向方面有缺点

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    相关资源
    最近更新 更多