在Windows上,控制台中有一些基本的表情符号支持,因此如果我键入,我可以获得单色字形,例如☕
或📜
. 我可以从PowerShell或C#控制台应用程序或Python输出字符串,它们都足够精细地显示这些字符。
但是,从 Node.js,我只能显示几个表情符号(例如☕
),但不是其他(而不是我看到�
📜
)。 但是,如果我throw
包含这些字符的字符串,它们会正确显示。
console.log(' 📜 ☕ ');
throw ' 📜 ☕ ';
如果我运行上面的脚本,输出是
� ☕ C:Codeemojitestemojitest.js:2 throw ' 📜 ☕ '; ^ 📜 ☕
无论如何,我可以正确输出这些表情符号而不会引发错误吗? 或者该异常是否发生在我通过标准 Node.js API 可用的范围之外?
如果不更改libuv,您可能不可能实现您想要的。当您(或 控制台)写入 Windows 上的stdout
或stderr
,并且流是 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()
在 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控制台中打印到stdout
或stderr
时,控制台似乎会在打印之前执行一些(错误的)重新编码工作。当程序直接使用 Windows 控制台 API 时(使用MultiByteToWideChar
本身进行转换,然后使用WriteConsoleW()
写入控制台),控制台会显示光荣的未更改表情符号。
当JS程序使用console
API来记录内容时,也许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