如何在 Node.js(在 Windows)中将表情符号输出到控制台?

How to output emoji to console in Node.js (on Windows)?

在 Windows 上,控制台中有一些基本的表情符号支持,因此我可以在键入时获得单色字形,例如</code>。我可以从 PowerShell 或 C# 控制台应用程序或 Python 输出一个字符串,它们都能很好地显示这些字符。</p> <p>然而,从Node.js,我只能得到几个表情符号来显示(例如<code>☕),而不是其他(而不是</code>我参见 <code>�)。但是,如果我 throw 一个包含这些字符的字符串,它们会正确显示。

console.log('  ☕ ');
throw '  ☕ ';

如果我运行上面的脚本,输出是

 � ☕

C:\Code\emojitest\emojitest.js:2
throw '  ☕ '; 
^
  ☕

有什么方法可以正确输出这些表情符号而不会出错?还是该异常发生在我可以通过标准 Node.js API 获得的内容之外?

如果不更改 libuv,您想要的可能无法实现。当你(或 console) 在 Windows 上写入 stdoutstderr 并且流是 TTY, libuv 自己进行从 UTF-8 到 UTF-16 的转换。这样做明确 拒绝输出代理对,而是发出替换字符 U+FFFD � 对于 BMP 之外的任何代码点。

这是 uv/src/win/tty.c 中的罪魁祸首:

  /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */
  /* windows console doesn't really support UTF-16, so just emit the */
  /* replacement character. */
  if (utf8_codepoint > 0xffff) {
    utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
  }

throw 消息正确显示,因为 Node 让 Windows 执行 使用 MultiByteToWideChar() 从 UTF-8 转换为 UTF-16(确实会发出 代理对)在将消息写入控制台之前。 (看 PrintErrorString() in src/node.cc.)

注意:已提交 pull request 来解决此问题。

(免责声明:我没有解决方案,我使用 Windows 上的工具探索了 打印表情符号 异常处理的特殊之处10 -- 运气好的话可能会在这个问题上找到一些线索,也许有人会认出一些东西并提出解决方案)

看起来像 Node 的 Windows 调用不同 Windows API 的异常报告代码,它恰好更好地支持 Unicode。

让我们看看 Node 7.10 来源:

ReportExceptionAppendExceptionLinePrintErrorString

PrintErrorString 中,Windows 特定部分 detects output type (tty/console or not): - 对于 non-tty/console 上下文,它将打印到 stderr(例如,如果您重定向到一个文件) - 在 cmd 控制台中(没有重定向),它将 convert text with MultiByteToWideChar() and then passWriteConsoleW().

如果我 运行 你的程序使用 ConEmu(比使用标准 cmd 使用 unicode 和表情符号更容易——是的,我在这里有点懒),我看到了一些东西与您看到的类似:console.log 无法打印表情符号,但异常消息中的表情符号打印正常(甚至滚动字形)。

如果我将所有输出重定向到一个文件(node test.js > out.txt 2>&1,是的,这在 Windows cmd 中也有效),在这两种情况下我都会得到 "clean" Unicode。

因此,当程序在 Windows 控制台中打印到 stdoutstderr 时,控制台似乎在打印之前做了一些(错误的)重新编码工作。当程序直接使用 Windows 控制台 API(使用 MultiByteToWideChar 本身进行转换,然后使用 WriteConsoleW() 写入控制台),控制台显示光荣的未更改表情符号。

当 JS 程序使用 console API 记录内容时,也许 Node 可以尝试(在 Windows 上)检测控制台并执行与报告异常相同的操作.请参阅 ,它解释了 libuv 中实际发生的事情。

下一个“Windows Terminal" (from Kayla Cinnamon) and the Microsoft/Terminal项目应该可以显示表情符号。

这将于 2019 年 6 月开始提供。 通过使用 Consolas 字体,将提供部分 Unicode 支持。

请求在 Microsoft/Terminal issue 387 中进行。
并且 Microsoft/Terminal issue 190 正式要求 "Add emoji support to Windows Console".

但仍有问题(2019 年 3 月):

I updated my Win10 from 1803 to 1809 several days ago, and now all characters >= U+10000 (UTF-8 with 4 bytes or more) no longer display.
I have also tried the newest insider version(Windows 10 Insider Preview 18358.1 (19h1_release)), unfortunately, this bug still exists.