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



在Windows上,控制台中有一些基本的表情符号支持,因此如果我键入,我可以获得单色字形,例如📜. 我可以从PowerShell或C#控制台应用程序或Python输出字符串,它们都足够精细地显示这些字符。

但是,从 Node.js,我只能显示几个表情符号(例如),但不是其他(而不是我看到📜)。 但是,如果我throw包含这些字符的字符串,它们会正确显示。

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

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

� ☕
C:Codeemojitestemojitest.js:2
throw ' 📜 ☕ '; 
^
📜 ☕

无论如何,我可以正确输出这些表情符号而不会引发错误吗? 或者该异常是否发生在我通过标准 Node.js API 可用的范围之外?

如果不更改libuv,您可能不可能实现您想要的。当您(或 控制台)写入 Windows 上的stdoutstderr,并且流是 TTY,libuv自行从 UTF-8 转换为 UTF-16。在这样做时,它明确地 拒绝输出代理项对,而是发出替换字符U+FFFDBMP 以外的任何代码点。

以下是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()在 src/node.cc 中)

注意:已提交拉取请求以解决此问题。

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

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

让我们看看 Node 7.10 源代码:

报告异常 → 追加异常行 → 打印错误字符串

PrintErrorString中,特定于Windows的部分检测输出类型(tty/控制台与否): - 对于非 tty/控制台上下文,它将打印到stderr(例如,如果您重定向到文件) - 在cmd控制台(无重定向)中,它将使用MultiByteToWideChar()转换文本,然后将其传递给WriteConsoleW()

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

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

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

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

下一个"Windows Terminal"(来自Kayla Cinnamon)和Microsoft/终端项目应该能够显示表情符号。

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

该请求正在Microsoft/Terminal第 387 期中处理中。
Microsoft/终端问题 190 正式要求"向 Windows 控制台添加表情符号支持"。

但仍存在问题(2019 年 3 月):

几天前,我将 Win10 从 1803 更新为 1809,现在所有字符>= U+10000(具有 4 个字节或更多的 UTF-8)不再显示。
我也尝试了最新的内部版本(Windows 10 预览体验版 18358.1 (19h1_release)),不幸的是,此错误仍然存在。

有一种简单的方法可以在控制台中记录表情符号:

console.log("u{1F9E1} Do what you love or love what you do!");
console.log("u{1F3AF}");

十六进制格式的表情符号代码参考:https://www.w3schools.com/charsets/ref_emoji.asp

最新更新