在命令提示符/ Windows Powershell(Windows 10)中使用UTF-8编码(CHCP 65001)

Using UTF-8 Encoding (CHCP 65001) in Command Prompt / Windows Powershell (Windows 10)

我一直在命令提示符和Windows Powershell中强制使用chcp 65001,但是从SO和其他几个社区的问答环节来看,这似乎是一种危险且低效的解决方案。 Microsoft是否提供了chcp 65001的改进/完整替代方案,可以在不手动更改注册表的情况下将其永久保存? 如果没有,将来是否有公开宣布的时间表或议程来支持Windows CLI中的UTF-8?

我个人一直在使用chcp 949来支持韩文字符,但是反斜杠 \ 的显示很奇怪,并且在某些应用程序(例如Neovim)中显示不正确/无法理解,并且不能通过以下方式支持不支持韩文的字符 949最近似乎变得越来越成问题。


注意:

  • 此答案显示了如何将Windows控制台中的字符编码切换为UTF-8(代码页65001),以便与外部(控制台)通信时,诸如cmd.exe和PowerShell的外壳程序可以正确地编码和解码字符(文本)。 PowerShell和cmd.exe中的程序也用于文件I / O.1

  • 相比之下,如果您关注控制台窗口中Unicode字符呈现限制的单独方面,请参阅此答案的中下部,在此还将讨论其他控制台(终端)应用程序。


  • Does Microsoft provide an improved / complete alternative to chcp 65001 that can be saved permanently without manual alteration of the Registry?

    Ok.

    从(至少)Windows 10版本1903起,您可以选择将系统区域设置(非Unicode程序的语言)设置为UTF-8,但在撰写本文时此功能处于beta版本。

    要激活它:

  • 运行intl.cpl(在"控制面板"中打开区域设置)
  • 请按照以下屏幕快照中的说明进行操作。
  • enter image description here

  • 这将使以后的所有控制台窗口默认为UTF-8(chcp 65001)。

  • 注意事项:

  • 如果您使用的是Windows PowerShell,这还将使Get-ContentSet-Content(可能还有Windows PowerShell默认的其他上下文,因此系统的活动ANSI代码页)默认为UTF-8(PowerShell Core(v6 +)始终会这样做) )。这意味着,在没有-Encoding参数的情况下,然后会误读经过ANSI编码的无BOM文件(这在历史上很常见),并且使用Set-Content创建的文件将为UTF-8,而不是ANSI-编码。

  • 至少在PowerShell 7.0之前,基础.NET版本(.NET Core 3.1)中的错误会导致PowerShell中的后续错误:通过stdin意外地将UTF-8 BOM传递给外部进程的数据(无论您使用什么)将$OutputEncoding设置为),这会明显破坏Start-Job-请参见此GitHub问题。

  • 并非所有字体都使用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中不再需要此功能,PowerShell Core在内部始终默认为无BOM的UTF-8。

  • 如果在您的环境中不能将系统语言环境设置为UTF-8,则使用启动命令代替:

    注意:上述注意事项在这里同样适用。如果运行旧版控制台应用程序对您来说很重要,请参阅注释中eryksun的建议。

  • 对于PowerShell(两个版本),将以下行添加到$PROFILE(仅当前用户)或$PROFILE.AllUsersCurrentHost(所有用户)文件中,该文件等效于chcp 65001,并补充设置首选项变量$OutputEncoding以指示PowerShell通过UTF-8中的管道将数据发送到外部程序:

  • 请注意,从PowerShell会话内部运行chcp 65001无效,因为.NET在启动时会缓存控制台的输出编码,并且不知道以后对chcp所做的更改;此外,如上所述,Windows PowerShell要求设置$OutputEncoding-有关详细信息,请参见此答案。
  • 1
    $OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding

  • 例如,以下是一种通过编程将这行添加到$PROFILE的快捷方法:
  • 1
    '$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding' + [Environment]::Newline + (Get-Content -Raw $PROFILE) | Set-Content -Encoding utf8 $PROFILE
  • 对于cmd.exe,通过注册表 HKEY_CURRENT_USER\\Software\\Microsoft\\Command Processor(仅当前用户)或HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Command Processor(所有用户)的值AutoRun定义一个自动运行命令:

  • 例如,您可以使用PowerShell为您创建此值:
  • 1
    2
    3
    # 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'

    可选阅读:为什么Windows PowerShell ISE是一个较差的选择:

    尽管ISE确实比控制台具有更好的Unicode渲染支持,但通常是一个差的选择:

  • 首先,ISE已过时:它不支持PowerShell Core,将来所有的开发都会进行下去,而且它也不是跨平台的,这与两个PowerShell版本的新的首要IDE(Visual Studio Code)不同默认情况下,PowerShell Core的UTF-8可以配置为Windows PowerShell。

  • ISE通常是一个用于开发脚本的环境,而不是用于在生产环境中运行它们的环境(如果您还为其他人编写脚本,则应假定它们将在控制台中运行)。值得注意的是,在运行脚本方面,ISE的行为在所有方面都不尽相同。

  • 正如eryksun所指出的,ISE不支持运行交互式外部控制台程序,即需要用户输入的程序:

  • The problem is that it hides the console and redirects the process output (but not input) to a pipe. Most console applications switch to full buffering when a file is a pipe. Also, interactive applications require reading from stdin, which isn't possible from a hidden console window. (It can be unhidden via ShowWindow, but a separate window for input is clunky.)

    Ok.

  • 如果您愿意遵守该限制,那么将活动代码页切换为65001(UTF-8)以便与外部程序进行正确的通信需要一种尴尬的解决方法:

  • 您必须首先通过运行内置控制台中的任何外部程序(例如chcp)来强制创建隐藏的控制台窗口-您会看到控制台窗口短暂闪烁。

  • 只有这样,您才能将[console]::OutputEncoding(和$OutputEncoding)设置为UTF-8,如上所示(如果尚未创建隐藏的控制台,则会得到一个handle is invalid error)。


  • 1在PowerShell中,如果您从不调用外部程序,则无需担心系统区域设置(活动代码页):PowerShell本地命令和.NET调用始终通过UTF-16字符串(本地.NET字符串)和文件进行通信I / O应用独立于系统区域设置的默认编码。同样,由于Windows API函数的Unicode版本用于向控制台打印和从控制台读取,因此非ASCII字符始终可以正确打印(在控制台的呈现限制内)。
    相比之下,在cmd.exe中,系统区域设置对于文件I / O也很重要(特别是包括批处理文件源代码采用的编码),而不仅仅是与外部程序进行通信,例如在读取< x6>循环。

    好。


    您可以将命令chcp 65001放在Powershell配置文件中,当您打开Powershell时它将自动运行它。但是,这对于cmd.exe不会执行任何操作。

    Microsoft当前正在开发一种改进的终端,该终端将具有完全的Unicode支持。它是开源的,如果您使用的是Windows 10版本1903或更高版本,则可以下载预览版本。

    或者,您可以使用第三方终端仿真器,例如Terminus。


    Powershell ISE可以完美显示韩语。这是可以使用utf8编码的示例文本文件:

    1
    2
    3
    4
    5
    PS C:\\Users\\js> cat .\\korean.txt

    The Korean language (South Korean: ???/韓國語 Hangugeo; North
    Korean: ???/朝鮮? Chos?nmal) is an East Asian language
    spoken by about 77 million people.[3]

    由于ISE随Windows 10的每个版本一起提供,因此我认为它已经过时了。我不同意删除原始答案的人。

    ISE有一些限制,但是可以使用外部命令来完成某些脚本编制:

    1
    2
    echo 'list volume' | diskpart # as admin
    cmd /c echo hi

    编辑:

    如果您使用的是Windows 10 1903,则可以从Microsoft商店https://devblogs.microsoft.com/commandline/introducing-windows-terminal/下载Windows Terminal,并且韩文文本可以在其中使用。 Powershell 5将需要文本格式为带有bom的UTF8或UTF16。

    编辑2:

    似乎理想的是Windows终端+ powershell 7或vscode + powershell 7,用于粘贴字符和输出。

    编辑3:

    即使在EDIT2情况下,也无法粘贴某些Unicode字符,例如?(U + 21C6)或Unicode空间。只有Osx中的PS7可以工作。