В какой кодировке работает консоль windows

Время на прочтение9 мин

Количество просмотров47K

Введение

Консольные приложения до сих пор остаются наиболее востребованным видом приложений, большинство разработчиков оттачивают архитектуру и бизнес-логику именно в консоли. При этом они нередко сталкиваются с проблемой локализации — русский текст, который вполне адекватно отражается в исходном файле, при выводе на консоль приобретает вид т.н. «кракозябр».

В целом, локализация консоли Windows при наличии соответствующего языкового пакета не представляется сложной. Тем не менее, полное и однозначное решение этой проблемы, в сущности, до сих пор не найдено. Причина этого, главным образом, кроется в самой природе консоли, которая, являясь компонентом системы, реализованным статическим классом System.Console, предоставляет свои методы приложению через системные программы-оболочки, такие как командная строка или командный процессор (cmd.exe), PowerShell, Terminal и другие.
По сути, консоль находится под двойным управлением — приложения и оболочки, что является потенциально конфликтной ситуацией, в первую очередь в части использования кодировок.

Данный материал не предлагает строгий алгоритм действий, а направлен на описание узловых проблем, с которыми неизбежно сталкивается разработчик локализованного консольного приложения, а также некоторые возможные пути их разрешения. Предполагается, что это позволит разработчику сформировать стратегию работы с локализованной консолью и эффективно реализовать существующие технические возможности, большая часть которых хорошо описана и здесь опущена.

Виды консолей

В общем случае функции консоли таковы:

  • управление операционной системой и системным окружением приложений на основе применения стандартных системных устройств ввода-вывода (экран и клавиатура), использования команд операционной системы и/или собственно консоли;

  • запуск приложений и обеспечение их доступа к стандартным потокам ввода-вывода системы, также с помощью стандартных системных устройств ввода-вывода.

Основная консоль Windows — командная строка или иначе командный процессор (CMD). Большие возможности предоставляют оболочки PowerShell (PS), Windows PowerShell (WPS) и Terminal. По умолчанию Windows устанавливает Windows Power Shell мажорной версией до 5, однако предлагает перейти на новую версию — 7-ку, имеющую принципиальное отличие (вероятно, начинающееся с 6-ки) — кроссплатформенность. Terminal — также отдельно уставливаемое приложение, по сути интегратор всех ранее установленных оболочек PowerShell и командной строки.

Отдельным видом консоли можно считать консоль отладки Visual Studio (CMD-D).

Конфликт кодировок

Полностью локализованная консоль в идеале должна поддерживать все мыслимые и немыслимые кодировки приложений, включая свои собственные команды и команды Windows, меняя «на лету» кодовые страницы потоков ввода и вывода. Задача нетривиальная, а иногда и невозможная — кодовые страницы DOS (CP437, CP866) плохо совмещаются с кодовыми страницами Windows и Unicode.

История кодировок здесь: О кодировках и кодовых страницах / Хабр (habr.com)

Исторически кодовой страницей Windows является CP1251 (Windows-1251, ANSI, Windows-Cyr), уверенно вытесняемая 8-битной кодировкой Юникода CP65001 (UTF-8, Unicode Transformation Format), в которой выполняется большинство современных приложений, особенно кроссплатформенных. Между тем, в целях совместимости с устаревшими файловыми системами, именно в консоли Windows сохраняет базовые кодировки DOS — CP437 (DOSLatinUS, OEM) и русифицированную CP866 (AltDOS, OEM).

Совет 1. Выполнять разработку текстовых файлов (программных кодов, текстовых данных и др.) исключительно в кодировке UTF-8. Мир любит Юникод, а кроссплатформенность без него вообще невозможна.

Совет 2. Периодически проверять кодировку, например в текстовом редакторе Notepad++. Visual Studio может сбивать кодировку, особенно при редактировании за пределами VS.

Поскольку в консоли постоянно происходит передача управления от приложений к собственно командному процессору и обратно, регулярно возникает «конфликт кодировок», наглядно иллюстрируемый таблица 1 и 2, сформированных следующим образом:

Были запущены три консоли — CMD, PS и WPS. В каждой консоли менялась кодовая страница с помощью команды CHCP, выполнялась команда Echo c двуязычной строкой в качестве параметра (табл. 1), а затем в консоли запускалось тестовое приложение, исходные файлы которого были созданы в кодировке UTF-8 (CP65001): первая строка формируется и направляется в поток главным модулем, вторая вызывается им же, формируется в подключаемой библиотеке классов и направляется в поток опять главным модулем, третья строка полностью формируется и направляется в поток подключаемой библиотекой.

Команды и код приложения под катом

команды консоли:

  • > Echo ffffff фффффф // в командной строке

  • PS> Echo ffffff фффффф // в PowerShell

  • PS> Echo ffffff ?????? // так выглядит та же команда в Windows PowerShell

код тестового приложения:

using System;
using ova.common.logging.LogConsole;
using Microsoft.Extensions.Logging;
using ova.common.logging.LogConsole.Colors;

namespace LoggingConsole.Test
{
    partial class Program
    {
        static void Main2(string[] args)
        {
            ColorLevels.ColorsDictionaryCreate();
            Console.WriteLine("Hello World! Привет, мир!");     //вывод строки приветствия на двух языках
            LogConsole.Write("Лог из стартового проекта", LogLevel.Information);
            Console.WriteLine($"8. Active codepage: input {Console.InputEncoding.CodePage}, output {Console.OutputEncoding.CodePage}");
            Console.ReadKey();
        } 
    }
}

Командную часть задания все консоли локализовали практически без сбоев во всех кодировках, за исключением: в WPS неверно отображена русскоязычная часть команды во всех кодировках.

Табл. 1. Результат выполнения команды консоли Echo ffffff фффффф

Вывод тестового приложения локализован лишь в 50% испытаний, как показано в табл.2.

Табл. 2. Результат запуска приложения LoggingConsole.Test

Табл. 2. Результат запуска приложения LoggingConsole.Test

Сoвет 3. Про PowerShell забываем раз и навсегда. Ну может не навсегда, а до следующей мажорной версии…

По умолчанию Windows устанавливает для консоли кодовые страницы DOS. Чаще всего CP437, иногда CP866. Актуальные версии командной строки cmd.exe способны локализовать приложения на основе русифицированной кодовой страницы 866, но не 437, отсюда и изначальный конфликт кодировок консоли и приложения. Поэтому

Совет 4. Перед запуском приложения необходимо проверить кодовую страницу консоли командой CHCP и ей же изменить кодировку на совместимую — 866, 1251, 65001.

Совет 5. Можно установить кодовую страницу консоли по умолчанию. Кратко: в разделе реестра \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor добавить или изменить значение параметра Autorun на: chcp <номер кодовой страницы>. Очень подробно здесь: Изменить кодовую страницу консоли Windows по умолчанию на UTF-8 (qastack.ru), оригинал на английском здесь: Change default code page of Windows console to UTF-8.

Проблемы консолей Visual Studio

В Visual Studio имеется возможность подключения консолей, по умолчанию подключены командная строка для разработчика и Windows PowerShell для разработчика. К достоинствам можно отнести возможности определения собственных параметров консоли, отдельных от общесистемных, а также запуск консоли непосредственно в директории разработки. В остальном — это обычные стандартные консоли Windows, включая, как показано ранее, установленную кодовую страницу по умолчанию.

Отдельной опцией Visual Studio является встроенная односеансная консоль отладки, которая перехватывает команду Visual Studio на запуск приложения, запускается сама, ожидает компиляцию приложения, запускает его и отдает ему управление. Таким образом, отладочная консоль в течение всего рабочего сеанса находится под управлением приложения и возможность использования команд Windows или самой консоли, включая команду CHCP, не предусмотрена. Более того, отладочная консоль не воспринимает кодовую страницу по умолчанию, определенную в реестре, и всегда запускается в кодировке 437 или 866.

Совет 6. Тестирование приложения целесообразно выполнять во внешних консолях, более дружелюбных к локализации.

Анализ проблем консолей был бы не полон без ответа на вопрос — можно ли запустить консольное приложение без консоли? Можно — любой файл «.exe» запустится двойным кликом, и даже откроется окно приложения. Однако консольное приложение, по крайней мере однопоточное, по двойному клику запустится, но консольный режим не поддержит — все консольные вводы-выводы будут проигнорированы, и приложение завершится

Локализация отладочной консоли Visual Studio

Отладочная консоль — наиболее востребованная консоль разработчика, гораздо более удобная, чем внешняя консоль, поэтому резонно приложить максимум усилий для ее локализации.

На самом деле, правильнее говорить о локализации приложения в консоли — это важное уточнение. Microsoft по этому поводу высказывается недвусмысленно: «Programs that you start after you assign a new code page use the new code page. However, programs (except Cmd.exe) that you started before assigning the new code page will continue to use the original code page». Иными словами, консоль можно локализовать когда угодно и как угодно, но приложение будет локализовано в момент стабилизации взаимодействия с консолью в соответствии с текущей локализацией консоли, и эта локализация сохранится до завершения работы приложения. В связи с этим возникает вопрос — в какой момент окончательно устанавливается связь консоли и приложения?

Важно! Приложение окончательно стабилизирует взаимодействие с консолью в момент начала ввода-вывода в консоль, благодаря чему и появляется возможность программного управления локализацией приложения в консоли — до первого оператора ввода-вывода.

Ниже приведен пример вывода тестового приложения в консоль, иллюстрирующий изложенное. Метод Write получает номера текущих страниц, устанавливает новые кодовые страницы вводного и выводного потоков, выполняет чтение с консоли и записывает выводную строку, содержащий русский текст, в том числе считанный с консоли, обратно в консоль. Операция повторяется несколько раз для всех основных кодовых страниц, упомянутых ранее.

F:\LoggingConsole.Test\bin\Release\net5.0>chcp
Active code page: 1251

F:\LoggingConsole.Test\bin\Release\net5.0>loggingconsole.test
Codepages: current 1251:1251, setted 437:437, ΓΓεΣΦ∞ 5 ±Φ∞ΓεδεΓ ∩ε-≡≤±±ΩΦ: Θ÷≤Ωσ=Θ÷≤Ωσ
Codepages: current 437:437, setted 65001:65001,  5  -: =
Codepages: current 65001:65001, setted 1252:1252, ââîäèì 5 ñèìâîëîâ ïî-ðóññêè: éöóêå=éöóêå
Codepages: current 1252:1252, setted 1251:1251, вводим 5 символов по-русски: йцуке=йцуке
Codepages: current 1251:1251, setted 866:866, ттюфшь 5 ёшьтюыют яю-Ёєёёъш: щЎєъх=щЎєъх
Codepages: current 866:866, setted 1251:1251, вводим 5 символов по-русски: йцуке=йцуке
Codepages: current 1251:1251, setted 1252:1252, ââîäèì 5 ñèìâîëîâ ïî-ðóññêè: éöóêå=éöóêå

F:\LoggingConsole.Test\bin\Release\net5.0>chcp
Active code page: 1252
  • приложение запущено в консоли с кодовыми страницами 1251 (строка 2);

  • приложение меняет кодовые страницы консоли (current, setted);

  • приложение остановлено в консоли с кодовыми страницами 1252 (строка 11, setted);

  • по окончании работы приложения изменения консоли сохраняются (строка 14 — Active codepage 1252);

  • Приложение адекватно локализовано только в случае совпадения текущих кодовых страниц консоли (setted 1251:1251) с начальными кодовыми страницами (строки 8 и 10).

Код тестового приложения под катом

using System;
using System.Runtime.InteropServices;

namespace LoggingConsole.Test
{
    partial class Program
    {
        [DllImport("kernel32.dll")] static extern uint GetConsoleCP();
        [DllImport("kernel32.dll")] static extern bool SetConsoleCP(uint pagenum);
        [DllImport("kernel32.dll")] static extern uint GetConsoleOutputCP();
        [DllImport("kernel32.dll")] static extern bool SetConsoleOutputCP(uint pagenum);
        
        static void Main(string[] args)
        {
            Write(437);
            Write(65001);
            Write(1252);
            Write(1251);
            Write(866);
            Write(1251);
            Write(1252);
         }

        static internal void Write(uint WantedIn, uint WantedOut)
        {
            uint CurrentIn = GetConsoleCP();
            uint CurrentOut = GetConsoleOutputCP();
            Console.Write($"current {CurrentIn}:{CurrentOut} - текущая кодировка, "); /*wanted {WantedIn}:{WantedOut},*/
            SetConsoleCP(WantedIn);
            SetConsoleOutputCP(WantedOut);
            Console.Write($"setted {GetConsoleCP()}:{GetConsoleOutputCP()} - новая кодировка, ");
            Console.Write($"вводим 3 символа по-русски: ");
            string str = "" + Console.ReadKey().KeyChar.ToString();
            str += Console.ReadKey().KeyChar.ToString();
            str += Console.ReadKey().KeyChar.ToString();
            Console.WriteLine($"={str}");
        }
      
        static internal void Write(uint ChangeTo)
        {
            Write(ChangeTo, ChangeTo);
        }
    }
}

Программное управление кодировками консоли — это единственный способ гарантированной адекватной локализацией приложения в консоли. Языки .Net такой возможности не предоставляют, однако предоставляют функции WinAPI: SetConsoleCP(uint numcp) и SetConsoleOutputCP(uint numcp), где numcp — номер кодовой страницы потоков ввода и вывода соответственно. Подробнее здесь: Console Functions — Windows Console | Microsoft Docs. Пример применения консольных функций WInAPI можно посмотреть в тестовом приложении под катом выше.

Совет 7. Обязательный и повторный! Функции SetConsoleCP должны размещаться в коде до первого оператора ввода-вывода в консоль.

Стратегия локализации приложения в консоли

  1. Удалить приложение PowerShell (если установлено), сохранив Windows PowerShell;

  2. Установить в качестве кодовую страницу консоли по умолчанию CP65001 (utf-8 Unicode) или CP1251 (Windows-1251-Cyr), см. совет 5;

  3. Разработку приложений выполнять в кодировке utf-8 Unicode;

  4. Контролировать кодировку файлов исходных кодов, текстовых файлов данных, например с помощью Notepad++;

  5. Реализовать программное управление локализацией приложения в консоли, пример ниже под катом:

Пример программной установки кодовой страницы и локализации приложения в консоли

using System;
using System.Runtime.InteropServices;

namespace LoggingConsole.Test
{
    partial class Program
    {
      	static void Main(string[] args)
        {
          	[DllImport("kernel32.dll")] static extern bool SetConsoleCP(uint pagenum);
        		[DllImport("kernel32.dll")] static extern bool SetConsoleOutputCP(uint pagenum);
            SetConsoleCP(65001);        //установка кодовой страницы utf-8 (Unicode) для вводного потока
            SetConsoleOutputCP(65001);  //установка кодовой страницы utf-8 (Unicode) для выводного потока
 
            Console.WriteLine($"Hello, World!");
        }
    }
}

Кракозябры в командной строке Windows


Добавил(а) microsin

  

Иногда по неизвестным причинам некоторые команды русскоязычной версии Windows выводят русский текст в нечитаемой кодировке, кракозябрами.

Например, команда help выводит нормальный текст:

cmd-normal-encoding-866

Но при этом подсказка telnet выводит в ответ кракозябры.

cmd-wrong-encoding-1251

Так может происходить, к примеру, если текущая кодировка консоли 866, а утилита telnet.exe почему-то выводит текст в кодировке 1251. Вывести текст в нужной кодировке поможет команда chcp, которая устанавливает нужную кодировку.

Вот так можно посмотреть текущую кодировку консоли:

c:\Documents and Settings\user>chcp
Текущая кодовая страница: 866
  
c:\Documents and Settings\user>

А вот так можно поменять кодировку на 1251, после чего вывод подсказки telnet будет отображаться нормально:

c:\Documents and Settings\user>chcp 1251
Текущая кодовая страница: 1251
  
c:\Documents and Settings\user>

cmd-normal-encoding-1251

К сожалению, заранее угадать, в какой кодировке выводится текст, невозможно, поэтому проще попробовать установить командой chcp разные кодировки, чтобы добиться правильного отображения русского текста. Обычно используются кодировки 866 (кодировка русского текста DOS), 1251 (кодировка русского текста Windows), 65001 (UTF-8).

[Шрифт cmd.exe]

Иногда кракозябры можно убрать, если выбрать в свойствах окна cmd.exe шрифт Lucida Console (по умолчанию там стоит «Точечные шрифты»).

[Ссылки]

1. Универсальный декодер — конвертер кириллицы.

По умолчанию cmd.exe использует кодировку cp866. Текущую кодировку можно посмотреть командой chcp. Иногда возникает необходимость использовать в терминале юникод. Для этого необходимо использовать шрифт «Lucida Console» и переключить кодировку командой
>chcp <codepage>
Где параметр <codepage> для UTF-8 равен 65001

Самый лучший способ изучения языка программирования С++ — это составление консольных программ. Структура консольного проекта максимально упрощена, так как нет графического режима, для которого необходимо подключение файлов ресурсов, классов и прочего, прочего. При составлении программы может понадобиться вывести некоторое текстовое сообщение в консоль. И если это сообщение написано на латинице, то в командной строке Windows оно будет отображаться корректно. А если текстовое сообщение написано на кириллице, то вместо передаваемого сообщения, будет отображаться непонятная последовательность букв  и символов (см. Рисунок 1). Реализуем программно то, что мы хотим сделать.

  • MVS
  • Code::Blocks
  • Dev-C++
  • QtCreator
// rus_text.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    cout << "Кириллица в консоли\n"; // передаём текстовое сообщение в командную строку windows
    system("pause");
    return 0;
}
// rus_text.cpp: определяет точку входа для консольного приложения.

#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    cout << "Кириллица в консоли\n"; // передаём текстовое сообщение в командную строку windows
    return 0;
}

Программа передаёт сообщение Кириллица в консоли в командную строку Windows, и на этом завершает свою работу (см. Рисунок 1).

CppStudio.com

╩шЁшыышЎр т ъюэёюыш
Для продолжения нажмите любую клавишу . . .

Рисунок 1 — Кириллица в консоли

В результате, вместо передаваемого сообщения отображается непонятная последовательность символов, называемая — козяблики. Возникает вопрос: «Почему так происходит?». Чтобы понять природу происхождения так называемых козябликов, необходимо обратиться к теме — представление символов букв в компьютерах.

Природа вычислительных машин такова, что они могут работать только с числами. Поэтому, для представления букв или символов необходимо их закодировать, то есть каждой букве или символу присвоить определённое число, которое будет являться его кодом. Так образовались таблицы кодирования символов. В связи с тем, что в мире существует более 2,5 тысяч языков, то для каждого алфавита создавались свои таблицы кодирования символов, вот почему существует большое количество таблиц кодирования символов. Так как мы программируем под Windows, то нас будут интересовать такие кодировочные таблицы: cp866, cp1251 и utf-8(стандарт Unicode).  Хотя уже давно разработан единый стандарт кодирования символов — Unicode, в Windows до сих пор используются несколько кодировочных таблиц, а именно — cp866cp1251. Использование нескольких таблиц кодирования символов и является причиной появления козябликов, вместо сообщения Кириллица в консоли.

Unicode — единый стандарт кодирования символов, позволяющий представить знаки всех письменных языков.

Таким образом стандарт Unicode присваивает каждому символу уникальный код, независимо от языка. Сейчас Unicode считается лучшим стандартом кодирования символов. Вернёмся к нашей проблеме — вывод кириллицы в консоль.

Так уж повелось, в командной строке Windows кодировка символов соответствует стандарту cp866. То есть все символы в командной строке Windows закодированы по кодировочной таблице cp866. Причём поменять кодировку в командной строке Windows нельзя. Просмотреть стандарт кодирования символов в консоли можно, с помощью команды GRAFTABL  (см. Рисунок 2).

Рисунок 2 — Кириллица в консоли

Во всех русскоязычных Windows кодировка cp1251 является стандартной 8 — битной кодировкой. И при создании проекта в MVS2010 этот стандарт кодирования символов наследуется проектом, то есть программой. Хотя кодировку для проекта в MVS2010 можно легко поменять, это не решает проблемы, так как консоль понимает только одну кодировку cp866, которой в MVS нет. В итоге, получается, что программа передаёт коды символов сообщения стандарта cp1251. Командная строка принимает эти коды и переводит их в символы, но уже по стандарту cp866, так как другого стандарта не знает. В итоге сообщение передано в консоль, но символы интерпретированы не правильно, вот так и появляются козяблики.

Решить данную проблему можно только одним способом — перед тем, как передать текст в консоль, необходимо его перекодировать  в стандарт кодирования символов cp866. Существует несколько способов преобразования кодов знаков из одного стандарта в другой, мы воспользуемся самым простым — настройка локали.

Локаль — это набор параметров: набор символов, язык пользователя, страна, часовой пояс и др. Локаль необходима для быстрой настройки пользовательского интерфейса, в зависимости от географического положения. В С++ есть функция setlocale(), которая выполняет перекодировку символов в соответствии с требуемым языком. Эта функция определена в заголовочном файле <clocale>. Переделаем программу, которая передает сообщение Кириллица в консоли в командную строку windows.

  • MVS
  • Code::Blocks
  • Dev-C++
  • QtCreator
// rus_text.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
#include <clocale>
using namespace std;

int main(int argc, char* argv[])
{
    setlocale(LC_CTYPE, "rus"); // вызов функции настройки локали
    cout << "Кириллица в консоли\n"; 
    system("pause");
    return 0;
}
// rus_text.cpp: определяет точку входа для консольного приложения.

#include <iostream>
#include <clocale>
using namespace std;

int main(int argc, char* argv[])
{
    setlocale(LC_CTYPE, "rus"); // вызов функции настройки локали
    cout << "Кириллица в консоли\n";
    return 0;
}

Функция setlocale() имеет два параметра, первый параметр — тип категории локали, в нашем случае LC_TYPE — набор символов, второй параметр — значение локали. Таким образом, сначала устанавливаем нужную локаль, в нашем случае — "rus", после чего, можно использовать кириллицу, для вывода сообщений в консоль (см. Рисунок 3).

CppStudio.com

Кириллица в консоли
Для продолжения нажмите любую клавишу . . .

Рисунок 3 — Кириллица в консоли

Вместо аргумента "rus" можно также писать "Russian", или оставлять пустые двойные кавычки, тогда набор символов будет такой же как и в ОС.

На первый взгляд функция setlocale() делает своё дело, но это только на первый взгляд. Суть в том, что данная функция работает только с потоком вывода, если же использовать поток ввода, то там будет все та же непонятная абракадабра. Переделаем уже разобранную нами программу, таким образом, чтобы строка сохранялась в переменную, после чего, выводилась на экран.

  • MVS
  • Code::Blocks
  • Dev-C++
  • QtCreator
// rus_text.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
#include <clocale>
using namespace std;

int main(int argc, char* argv[])
{
    setlocale(LC_CTYPE, "rus"); // не функционирует с потоком ввода
    char string[20]; 
    cin >> string; // вводим строку, используя Кириллицу (СТРОКА СОХРАНИТСЯ В ПЕРЕМЕННОЙ НЕ КОРРЕКТНО)
    cout << "\nвывод: "<< string << endl; // ввывод строки
    system("pause");
    return 0;
}
// rus_text.cpp: определяет точку входа для консольного приложения.

#include <iostream>
#include <clocale>
using namespace std;

int main(int argc, char* argv[])
{
    setlocale(LC_CTYPE, "rus"); // не функционирует с потоком ввода
    char string[20];
    cin >> string; // вводим строку, используя Кириллицу (СТРОКА СОХРАНИТСЯ В ПЕРЕМЕННОЙ НЕ КОРРЕКТНО)
    cout << "\nвывод: "<< string << endl; // ввывод строки
    return 0;
}

Результат работы программы на рисунке 4.

CppStudio.com

Кириллица в консоли

вывод: ?ЁаЁ<<Ёж 
Для продолжения нажмите любую клавишу . . .

Рисунок 4 — Кириллица в консоли

Как видно из рисунка 4, слово вывод напечаталось корректно, а вот содержимое строки string — нет. А всё потому, что функция setlocale() работает только с потоком вывода. Но как же быть с потоком ввода??? Есть немало способов решать данную проблему, мы рассмотрим лишь один из них. Для этого подключаем к проекту заголовочный файл <windows.h>. В файле содержатся прототипы функций SetConsoleCP() и SetConsoleOutputCP(), они-то нам и нужны. Аргументом этих функций является идентификатор кодовой страницы, нужная нам страница win-cp 1251. Функция SetConsoleCP() устанавливает нужную кодовую таблицу, на поток ввода, тогда как функция SetConsoleOutputCP()  устанавливает нужную кодовую таблицу, на поток вывода.

// прототипы функций
BOOL WINAPI SetConsoleOutputCP (  __in UINT wCodePageID); // установка кодовой страницы в поток вывода
BOOL WINAPI SetConsoleCP (  __in UINT wCodePageID); // установка кодовой страницы в поток ввода
// где wCodePageID - идентификатор кодовой таблицы

Есть один весомый недостаток у данных функций — они работают со шрифтом Lucida Console. По умолчанию в консоли стоит шрифт Consolas. Поэтому в командной строке необходимо настроить используемый шрифт. Для этого открываемcmd, заходим в свойства, в закладке Шрифт выбираем Lucida Console, нажимаем ОК и на этом настройка завершена (см. Рисунок 5).

Кириллица в консоли

Рисунок 5 — Кириллица в консоли

Если все сделали правильно, то в консоли корректно будут отображаться символы Кириллицы. Теперь вместо функции setlocale() воспользуемся этими функциями.

  • MVS
  • Code::Blocks
  • Dev-C++
  • QtCreator
// rus_text.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;

int main(int argc, char* argv[])
{
    SetConsoleCP(1251);// установка кодовой страницы win-cp 1251 в поток ввода
    SetConsoleOutputCP(1251); // установка кодовой страницы win-cp 1251 в поток вывода

    char string[20]; 
    cin >> string; // вводим строку, используя Кириллицу 
    cout << "\nвывод: "<< string << endl; // ввывод строки
    system("pause");
    return 0;
}
// rus_text.cpp: определяет точку входа для консольного приложения.

#include <iostream>
#include <Windows.h>
using namespace std;

int main(int argc, char* argv[])
{
    SetConsoleCP(1251);// установка кодовой страницы win-cp 1251 в поток ввода
    SetConsoleOutputCP(1251); // установка кодовой страницы win-cp 1251 в поток вывода

    char string[20];
    cin >> string; // вводим строку, используя Кириллицу
    cout << "\nвывод: "<< string << endl; // ввывод строки
    return 0;
}

Результат работы программы показан на рисунке 6.

CppStudio.com

Кириллица в консоли

вывод: Кириллица
Для продолжения нажмите любую клавишу . . .

Рисунок 6 — Кириллица в консоли

  1. Unicode in PowerShell

  2. Change System Locale to Use UTF-8 Encoding in Windows PowerShell

  3. Set Encoding in $PSDefaultParameterValues Variable to Use UTF-8 Encoding in Windows PowerShell

  4. Use the chcp Command to Switch to UTF-8 Encoding in Windows PowerShell

  5. Benefits of Using UTF-8 Encoding in PowerShell

  6. Conclusion

UTF-8 Encoding (CHCP 65001) in PowerShell

UTF-8 encoding, represented by CHCP 65001 in PowerShell, is a pivotal tool for working with multilingual and special characters in the console.

This article will provide a comprehensive guide on how to utilize UTF-8 encoding in PowerShell, from understanding its significance to practical implementation.

Unicode in PowerShell

Unicode is a worldwide character encoding standard. It defines how characters in text files, web pages, and other documents are represented.

The computer system uses Unicode to manipulate characters and strings. The default encoding in PowerShell is Windows-1252.

Unicode was developed to support characters from all languages of the world. PowerShell supports a Unicode character encoding by default.

UTF-8 and UTF-16 are the most common Unicode encodings. PowerShell always uses BOM in all Unicode encodings except UTF7.

The BOM (byte-order-mark) is a Unicode signature included in the first few bytes of a file or text stream that indicates the Unicode encoding.

Understanding UTF-8 Encoding

UTF-8 is a character encoding standard that uses variable-width encoding to represent text. It’s capable of encoding virtually all characters in Unicode, making it the most widely used character encoding on the internet.

In the context of PowerShell, UTF-8 encoding ensures that characters from different languages, symbols, and special characters are displayed and processed correctly in the console window.

Change System Locale to Use UTF-8 Encoding in Windows PowerShell

There is an option to change the system locale (current language for non-Unicode programs) in Windows. But this feature is still in beta.

Go to Region Settings from the Control Panel or open intl.cpl from the Run program (Windows+R).

change system locale to use UTF-8 encoding in PowerShell

Open the Administrative tab and click Change system locale. Then, check the Beta option, as shown in the image below.

use unicode UTF-8 for worldwide language support

After that, press OK and restart the computer to apply the settings.

After restarting the computer, you can check the $OutputEncoding variable to view the current encoding.

Output:

As you can see, the current encoding is Unicode (UTF-8).

BodyName          : utf-8
EncodingName      : Unicode (UTF-8)
HeaderName        : utf-8
WebName           : utf-8
WindowsCodePage   : 1200
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
IsSingleByte      : False
EncoderFallback   : System.Text.EncoderReplacementFallback
DecoderFallback   : System.Text.DecoderReplacementFallback
IsReadOnly        : True
CodePage          : 65001

Now, you can view the characters of other languages in PowerShell.

Output:

Set Encoding in $PSDefaultParameterValues Variable to Use UTF-8 Encoding in Windows PowerShell

$PSDefaultParameterValues is a built-in automatic variable in PowerShell that allows you to set default values for cmdlet parameters. This means you can specify default values for parameters of cmdlets without having to explicitly provide them every time you use the cmdlet.

You can run the following command to activate the UTF-8 encoding in PowerShell.

$PSDefaultParameterValues = @{'*:Encoding' = 'utf8' }

It is only valid for the current PowerShell console. It will be reset to default after you exit the PowerShell window.

Output:

Several cmdlets in PowerShell have the -Encoding parameter to specify the encoding for different character sets. Some of them are Add-Content, Set-Content, Get-Content, Export-Csv, Out-File, etc.

The -Encoding parameter supports these values: ascii, bigendianunicode, oem, unicode, utf7, utf8, utf8BOM, utf8NoBOM, utf32.

Use the chcp Command to Switch to UTF-8 Encoding in Windows PowerShell

To switch to UTF-8 encoding in PowerShell, use the chcp command followed by 65001:

This command tells PowerShell to use UTF-8 encoding for character input and output.

Here’s what this command does in detail:

  • chcp: This is a command in the Windows command prompt and PowerShell. It stands for "Change Code Page". The code page determines how characters are encoded and displayed in the console window.

  • 65001: In this context, 65001 represents the code page for UTF-8 encoding. UTF-8 is a variable-width character encoding capable of encoding all possible characters, or code points, in Unicode.

    • UTF-8: It’s a widely used character encoding that can represent almost all characters from all human languages. It’s especially prevalent on the internet.
  • Changing to UTF-8 (65001): When you run chcp 65001, you’re telling PowerShell to use UTF-8 encoding for character input and output in the console. This can be helpful when working with text data that includes characters from different languages and symbols.

    For instance, if you’re dealing with files or data that contain non-English characters, setting the code page to UTF-8 ensures that these characters are displayed correctly in the console.

Resetting to Default Code Page

Remember that changing the code page might affect how some console applications behave, so it’s generally a good practice to reset it to the default code page (usually 437 for English) when you’re done using UTF-8.

To reset the code page to the default, you can use the command:

This will switch back to the default code page for your system, which is suitable for English text.

Benefits of Using UTF-8 Encoding in PowerShell

  1. Multilingual Support: UTF-8 allows PowerShell to handle text in multiple languages, ensuring correct display and processing of characters from different scripts.
  2. Special Characters: It’s crucial when dealing with special characters like emojis or mathematical symbols that aren’t represented in standard encodings.
  3. File Handling: When working with text files that include characters from various languages, using UTF-8 ensures accurate file operations.
  4. Data Processing: If you’re working with data that contains non-English characters, setting the code page to UTF-8 ensures correct handling and processing.

Potential Considerations

  1. Console Applications: Changing the code page might affect how some console applications behave. Always reset to the default code page (chcp 437 for English) when done using UTF-8.
  2. Compatibility: Ensure that the programs or scripts you’re running in PowerShell can handle UTF-8 encoding. Older applications may not fully support it.

Practical Use Cases

  1. Reading Files: When reading text files with non-English characters, using UTF-8 ensures accurate representation.
  2. Web Scraping: If you’re extracting text from websites that may contain characters from various languages, UTF-8 ensures correct interpretation.
  3. Script Outputs: If your scripts generate outputs with non-English characters, using UTF-8 ensures they are displayed correctly.
  4. Interactive PowerShell Sessions: For interactive sessions where you need to input or output text with special characters, UTF-8 encoding is invaluable.

Conclusion

UTF-8 encoding (CHCP 65001) in PowerShell is a powerful tool for handling multilingual and special characters in the console. It allows for accurate representation and processing of text from various languages and scripts. Understanding when and how to use UTF-8 encoding ensures a seamless experience when working with diverse sets of characters.

Remember to consider the compatibility of programs or scripts with UTF-8 and always revert to the default code page when necessary. By harnessing the power of UTF-8 encoding, you’ll be equipped to handle a wide range of text data with confidence and accuracy in PowerShell.

Enjoying our tutorials? Subscribe to DelftStack on YouTube to support us in creating more high-quality video guides. Subscribe

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Как удалить microsoft edge в windows 10 полностью через командную строку
  • Самые маленькие сборки windows 11
  • Как установить amazon appstore на windows 11 в россии
  • Windows 10 ltsc iso microsoft
  • Редактирование фото средствами windows