Использование кодировки UTF-8 (CHCP 65001) в командной строке / Windows Powershell (Windows 10)
Я заставлял использование chcp 65001
в командной строке и Windows Powershell в течение некоторого времени, но, судя по постам вопросов и ответов в SO и некоторых других сообществах, это кажется опасным и неэффективным решением. Предоставляет ли Microsoft улучшенную / полную альтернативу chcp 65001
что можно сохранить навсегда без изменения реестра вручную? И если нет, есть ли публично объявленные сроки или повестка дня для поддержки UTF-8 в Windows CLI в будущем?
Лично я пользуюсь chcp 949
для поддержки корейских символов, но странное отображение обратной косой черты \ и неправильное / непонятное отображение в нескольких приложениях (например, Neovim), а также символы, которые не являются корейскими, не поддерживаются через 949
Кажется, в последнее время стало больше проблем.
4 ответа
Примечание:
Этот ответ показывает, как переключить кодировку символов в консоли Windows на UTF-8 (кодовая страница
65001
), так что снаряды, такие какcmd.exe
и PowerShell правильно кодируют и декодируют символы (текст) при взаимодействии с внешними (консольными) программами в PowerShell, а также вcmd.exe
также для файлового ввода / вывода. 1Если, напротив, вас беспокоит отдельный аспект ограничений рендеринга символов Unicode в консольных окнах, см. Средний и нижний разделы этого ответа, где также обсуждаются альтернативные консольные (терминальные) приложения.
Предоставляет ли Microsoft улучшенную / полную альтернативу chcp 65001, которую можно сохранить навсегда без изменения реестра вручную?
Начиная с (по крайней мере) Windows 10 версии 1903, вы можете установить системный языковой стандарт (язык для программ, не поддерживающих Юникод) в UTF-8, но эта функция находится в стадии бета-тестирования на момент написания этой статьи.
Чтобы активировать его:
- Бегать
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, который по умолчанию внутренне согласован с UTF-8 без спецификации.
- Вы должны дополнительно установить
Если настройка языкового стандарта системы на UTF-8 не подходит для вашей среды, используйте вместо этого команды запуска:
Примечание: упомянутые выше caveat re legacy консольные приложения в равной степени применимы и здесь. Если для вас важно запускать устаревшие консольные приложения, см. Рекомендации 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'
Необязательное чтение: почему Windows PowerShell ISE является плохим выбором:
Хотя ISE имеет лучшую поддержку рендеринга Unicode, чем консоль, обычно это плохой выбор:
Прежде всего, ISE устарел: он не поддерживает PowerShell Core, куда пойдет вся дальнейшая разработка, и не является кроссплатформенным, в отличие от новой основной IDE для обеих редакций PowerShell, Visual Studio Code, которая уже говорит UTF-8 по умолчанию для PowerShell Core и может быть настроен для Windows PowerShell.
ISE, как правило, является средой для разработки сценариев, а не для запуска их в производстве (если вы пишете сценарии (также) для других, вы должны предполагать, что они будут выполняться в консоли); Примечательно, что поведение ISE не одинаково во всех аспектах, когда дело доходит до запуска сценариев.
Как указывает eryksun, ISE не поддерживает запуск программ интерактивной внешней консоли, а именно тех, которые требуют пользовательского ввода:
Проблема в том, что он скрывает консоль и перенаправляет вывод процесса (но не ввод) в канал. Большинство консольных приложений переключаются на полную буферизацию, когда файл представляет собой канал. Кроме того, интерактивные приложения требуют чтения из стандартного ввода, что невозможно из скрытого консольного окна. (Это может быть скрыто через
ShowWindow
, но отдельное окно для ввода неуклюже.)
Если вы хотите жить с этим ограничением, переключите активную кодовую страницу на
65001
(UTF-8) для правильного взаимодействия с внешними программами требуется неловкий обходной путь:Сначала вы должны принудительно создать скрытое окно консоли, запустив любую внешнюю программу из встроенной консоли, например:
chcp
- вы увидите кратковременное мигание окна консоли.Только тогда вы можете установить
[console]::OutputEncoding
(а также$OutputEncoding
) в UTF-8, как показано выше (если скрытая консоль еще не была создана, вы получитеhandle is invalid error
).
1 В PowerShell, если вы никогда не вызываете внешние программы, вам не нужно беспокоиться о локали системы (активные кодовые страницы): собственные команды PowerShell и вызовы.NET всегда взаимодействуют через строки UTF-16 (собственные строки.NET) и в файле. Ввод-вывод применяет кодировки по умолчанию, которые не зависят от языкового стандарта системы. Точно так же, поскольку версии Unicode функций Windows API используются для печати и чтения из консоли, символы, не входящие в ASCII, всегда печатаются правильно (в пределах ограничений рендеринга консоли).
В cmd.exe
Напротив, языковой стандарт системы имеет значение и для файлового ввода-вывода (в частности, включая кодировку для исходного кода пакетного файла), а не только для связи с внешними программами, например, при чтении вывода программы в for /f
петля.
Вы можете поставить команду chcp 65001
в вашем профиле Powershell, который будет запускаться автоматически при открытии Powershell. Тем не менее, это ничего не сделает для cmd.exe.
В настоящее время Microsoft работает над улучшенным терминалом, который будет иметь полную поддержку Unicode. Это открытый исходный код, и если вы используете Windows 10 версии 1903 или более поздней, вы уже можете скачать предварительную версию.
В качестве альтернативы вы можете использовать сторонний эмулятор терминала, такой как Terminus.
Набрав несколько команд (chcp
или что-то еще) всякий раз, когда запуск командной строки можно выполнить с помощью редактирования реестра . Это правильный путь, как это описано вCMD /?
:
Если /D НЕ был указан в командной строке, то при запуске CMD.EXE он ищет следующие переменные реестра REG_SZ/REG_EXPAND_SZ, и если одна из них или обе присутствуют, они выполняются первыми.
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun and/or HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
Сейчас 2023 год и хорошие новости. При использовании Windows Terminal редактирование реестра или создание дополнительного пакетного файла не требуется. В терминале Windows выберите «Настройки» > «Профили» , найдите «Командная строка», а затем измените командную строку с%SystemRoot%\System32\cmd.exe
(по умолчанию)%SystemRoot%\System32\cmd.exe /K "chcp 65001"
. Это просто.
Powershell ISE отлично отображает корейский. Вот пример текстового файла, закодированного в utf8, который будет работать:
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 имеет некоторые ограничения, но некоторые сценарии могут быть выполнены с помощью внешних команд:
echo 'list volume' | diskpart # as admin
cmd /c echo hi