我已经chcp 65001
在命令提示符和Windows Powershell中强制使用了一段时间,但是从SO和其他几个社区的问答环节来看,这似乎是一种危险且低效的解决方案。Microsoft是否提供一种chcp 65001
可以永久保存而无需手动更改注册表的改进/完整替代方案?如果没有,将来是否有公开宣布的时间表或议程来支持Windows CLI中的UTF-8?
我个人已经使用了chcp 949
韩国字符支持,但反斜线的怪异显示\在多个应用程序(如Neovim),以及字符和不正确/难以理解的显示器是不是韩国未通过支持949
似乎变得更加的最近有问题。
注意:
此答案显示了如何将Windows控制台中的字符编码切换为UTF-8(代码页65001
),以便诸如和PowerShell的外壳在PowerShell中以及与外部(控制台)程序进行通信时可以cmd.exe
正确地编码和解码字符(文本)。也用于文件I / O。1个cmd.exe
相比之下,如果您关注控制台窗口中Unicode字符呈现限制的单独方面,请参阅此答案的中下部,在本章中还将讨论其他控制台(终端)应用程序。
Microsoft是否提供了chcp 65001的改进/完整替代方案,可以永久保存而无需手动更改注册表?
从(至少)Windows 10版本1903起,您可以选择将系统区域设置(非Unicode程序的语言)设置为UTF-8,但是在撰写本文时此功能处于beta版本。
要激活它:
运行intl.cpl
(在“控制面板” 中打开区域设置)
请按照以下屏幕快照中的说明进行操作。
这将使以后的所有控制台窗口都默认为UTF-8(chcp 65001
)。
注意事项:
并非所有字体都使用Unicode,因此请选择TT(TrueType)字体,但即使它们通常仅支持所有字符的一个子集,因此您可能必须尝试使用特定字体以查看是否关注的所有字符都已表示-请参阅此答案有关详细信息,还讨论了具有更好的Unicode渲染支持的替代控制台(终端)应用程序。
正如eryksun指出的那样,不“讲” UTF-8的旧式控制台应用程序将仅限于纯ASCII输入,并且在尝试输出(7位)ASCII范围之外的字符时将产生错误的输出。(在过时的Windows 7及更低版本中,程序甚至可能崩溃)。
如果运行旧版控制台应用程序对您来说很重要,请参阅注释中eryksun的建议。
但是,对于Windows PowerShell而言,这还不够:
您必须另外在设置$OutputEncoding
选项变量为UTF-8 ,以及:$OutputEncoding = System.Text.UTF8Encoding
; 将命令添加到您的$PROFILE
(仅当前用户)或$PROFILE.AllUsersCurrentHost
(所有用户)文件中是最简单的。
幸运的是,在PowerShell Core中不再需要此功能,后者在内部始终默认为无BOM的UTF-8。
如果在您的环境中不能将系统区域设置设置为UTF-8 ,请使用启动命令代替:
注意:以上所述的旧版控制台应用程序同样适用于此。如果运行旧版控制台应用程序对您来说很重要,请参阅注释中eryksun的建议。
对于PowerShell(两个版本),将以下行添加到您的$PROFILE
(仅当前用户)或$PROFILE.AllUsersCurrentHost
(所有用户)文件中,等效于chcp 65001
,并补充设置首选项变量,$OutputEncoding
以指示PowerShell通过UTF中的管道将数据发送到外部程序-8:
需要注意的是运行chcp 65001
从里面一个PowerShell会话是不是有效,因为.NET缓存启动时的控制台输出编码,并没有意识到后来会更改与制作chcp
; 此外,如上所述,需要设置Windows PowerShell-有关详细信息,$OutputEncoding
请参见此答案。
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
例如,以下是一种快速方法,可以以$PROFILE
编程方式添加此行:
'$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding' + [Environment]::Newline + (Get-Content -Raw $PROFILE) | Set-Content -Encoding utf8 $PROFILE
对于cmd.exe
,请通过注册表AutoRun
以键HKEY_CURRENT_USER\Software\Microsoft\Command Processor
(仅当前用户)或HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor
(所有用户)的值定义自动运行命令:
例如,您可以使用PowerShell为您创建此值:
# Auto-execute `chcp 65001` whenever the current user opens a `cmd.exe` console # window (including when running a batch file): Set-ItemProperty 'HKCU:\Software\Microsoft\Command Processor' AutoRun 'chcp 65001 >NUL'
尽管ISE的确比控制台具有更好的Unicode 渲染支持,但通常是一个差的选择:
首先,ISE已过时:它不支持PowerShell Core,将来所有的开发都会进行下去,并且它也不是跨平台的,这与两个PowerShell版本的新的首要IDE(Visual Studio Code)不同。默认情况下,PowerShell Core的 UTF-8 可以配置为Windows PowerShell。
ISE通常是一个用于开发脚本的环境,而不是用于在生产环境中运行它们的环境(如果您还为其他人编写脚本,则应假定它们将在控制台中运行)。值得注意的是,在运行脚本方面,ISE的行为在所有方面都不尽相同。
正如eryksun指出的那样,ISE不支持运行交互式外部控制台程序,即需要用户输入的程序:
问题在于它隐藏了控制台,并将流程输出(而不是输入)重定向到管道。当文件是管道时,大多数控制台应用程序会切换到完全缓冲。另外,交互式应用程序需要从stdin读取,而这在隐藏的控制台窗口中是不可能的。(可以通过取消隐藏
ShowWindow
,但是单独的输入窗口很笨拙。)
如果您愿意遵守该限制,那么将活动代码页切换到65001
(UTF-8)以便与外部程序进行正确的通信需要一种尴尬的解决方法:
您必须首先通过从内置控制台运行任何外部程序来强制创建隐藏的控制台窗口,例如chcp
-您将看到控制台窗口短暂闪烁。
如上所示,只有到那时才能将UTF-8 设置[console]::OutputEncoding
(和$OutputEncoding
)(如果尚未创建隐藏的控制台,则会得到handle is invalid error
)。
1在PowerShell中,如果您从不调用外部程序,则不必担心系统区域设置(活动代码页):PowerShell本地命令和.NET调用始终通过UTF-16字符串(本地.NET字符串)和文件进行通信I / O应用独立于系统区域设置的默认编码。同样,由于Windows API函数的Unicode版本用于向控制台打印和从控制台读取,因此非ASCII字符始终可以正确打印(在控制台的呈现限制内)。
与之cmd.exe
相对,在系统区域设置中,系统区域设置也与文件I / O有关(特别是对于批处理文件源代码采用何种编码),而不仅仅是与外部程序通信,例如在for /f
循环读取程序输出时。