Почему Windows использует кодовую страницу ANSI вместо UNICODE?

Когда я запускаю команду chcp в окне cmd.exe, она представляет собой кодовую страницу, используемую в Windows.

Я думаю, что Windows использует набор символов UNICODE.

Итак, мои вопросы:

  1. Почему Windows использует кодовые страницы ANSI вместо Unicode?

  2. Windows использует UTF-16 или UCS-2? Могу ли я проверить это (командой или ссылкой MSDN)?

  3. UTF-16 или UCS-2 - это просто кодировка? или это тоже набор символов?

  4. UTF-8, UTF-16, UTF-32 и т. д. у них разный размер набора символов?

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


person JaeHyeok Kim    schedule 11.10.2017    source источник
comment
Изменение кодовой страницы консоли влияет только на приложения, не поддерживающие Unicode. Насколько я знаю, консоль по-прежнему поддерживает только UCS-2, но, конечно, большинство приложений Windows имеют графический интерфейс и в любом случае не используют консоль.   -  person Harry Johnston    schedule 11.10.2017
comment
Ячейки символов в консоли используют 16-битный код символов. Это ограничивает то, что он может отображать в BMP. Суррогатную пару UTF-16 можно записать в соседние ячейки, и в этом случае они будут отображаться как два глифа по умолчанию, например вопросительный знак в рамке. FWIW, вы можете скопировать и вставить суррогатную пару в другое окно. Консоль также не использует Uniscribe или DirectWrite, поэтому нет поддержки сложных сценариев, комбинирования символов и автоматических резервных шрифтов. Вы можете улучшить охват глифов с помощью ручной привязки шрифтов в реестре.   -  person Eryk Sun    schedule 11.10.2017
comment
1) Почему Windows использует кодовую страницу ANSI вместо UNICODE? на самом деле консоль использует как Unicode, так и многобайтовый API. все внутренние функции использовали Unicode. текст отображается как Unicode. CP используется только для перевода ввода/вывода Unicode ‹-› мультибайта. если мы вызовем WriteConsoleW, текст будет отображаться как есть, и текущий CP не будет иметь никакого эффекта. если мы вызовем WriteConsoleA - сначала текст будет переведен в Unicode через MultiByteToWideChar и здесь CP будет использоваться в качестве первого аргумента. поэтому A результат вызова API зависит от текущего CP, а W нет. и chcp будет действовать только для текущего cmd.exe   -  person RbMm    schedule 11.10.2017
comment
@RbMm, я полагаю, вы имеете в виду текущую консоль, а не только оболочку CMD, прикрепленную к консоли. CMD — это просто консольное клиентское приложение, как и любое другое консольное приложение. chcp.com — это простое консольное приложение, которое вызывает GetConsoleCP, SetConsoleCP и SetConsoleOutputCP. Это не позволяет установить выходную кодовую клавиатуру независимо от входной кодовой страницы. Примечательно, что входные и выходные кодовые страницы консоли используются при использовании ее в качестве общего файла через ReadFile и WriteFile, для которых UTF-16LE (кодовая страница 1200) не поддерживается.   -  person Eryk Sun    schedule 11.10.2017
comment
Спасибо за ваш ответ. Я добавил 4-й вопрос, пожалуйста, ответьте на него.   -  person JaeHyeok Kim    schedule 11.10.2017
comment
@eryksun - да :) если быть точным, я имею в виду conhost.exe (консольный серверный процесс), к которому прикреплены cmd.exe и chcp.com слишком. а вызов из SetConsole[Output]CP в любом процессе, прикрепленном к консоли (conhost.exe) приводит к вызову SrvSetConsoleCP в conhost.exe, который собственно и задает CP. поэтому CP это только переменная/состояние в conhost.exe и связанные с ним затронутые процессы. если мы выполним новый cmd из текущего - это тоже повлияет на него (прикрепленный к тому же conhost.exe), но если выполнить cmd из проводника - он будет иметь отдельный conhost.exe и никакого эффекта от этого   -  person RbMm    schedule 11.10.2017
comment
поэтому кодовая страница (в консольном серверном процессе conhost.exe) является переменной, используемой для выполнения преобразования многобайтового ‹-› Unicode, когда используется версия ansi api или файл чтения-записи (на консоль). но это уже подробности. если мы используем API W для интерактивной консоли - никакое преобразование и текущий CP не имеют никакого эффекта   -  person RbMm    schedule 11.10.2017
comment
@RbMm, как правило, мы не должны рассматривать недокументированные детали реализации, но нам нужно знать об ошибках. Например, использование 65001 (UTF-8) для выходной кодовой страницы было ошибочным до Windows 8, поскольку WriteFile и WriteConsoleA возвращали количество записанных кодов UTF-16 вместо количества записанных байтов. Хуже того, установка входной кодовой страницы на 65001 приводит к сбою при чтении ввода за пределами 7-битного ASCII даже в обновлении Windows 10 Creators из-за статических предположений о количестве байтов ANSI на символ при определении размера внутреннего буфера, используемого для вызова WideCharToMultiByte.   -  person Eryk Sun    schedule 11.10.2017
comment
@RbMm, еще одно внутреннее изменение (IMO на самом деле не ошибка) заключается в том, что новая консоль в Windows 10 больше не вызывает MultiByteToWideChar (для WriteConsoleA/WriteFile) с флагом MB_USEGLYPHCHARS. В старой реализации консоли этот флаг использовался для замены классических глифов OEM-компьютеров на управляющие символы ASCII. Возможно, это усовершенствование, поскольку в буфер экрана в новой консоли записаны именно символы ASCII, а не неявно подставленные символы.   -  person Eryk Sun    schedule 11.10.2017
comment
Ваше второе предложение противоречит вашему первому вопросу. Просьба уточнить.   -  person user207421    schedule 12.10.2017


Ответы (1)


  1. Исторические причины и обратная совместимость. Сама Windows является ОС на основе Unicode, и так было со времен NT. Но многие устаревшие (и даже текущие) приложения не написаны для Unicode. Приложения с поддержкой Unicode не используют кодовые страницы ANSI, если только им не нужно преобразовывать данные среды выполнения между ANSI и Unicode.

  2. Microsoft перешла на UTF-16 в Windows 2000. До этого она использовала UCS-2. См. Юникод в Microsoft Windows.

  3. И UTF-16, и UCS-2 — это просто кодировки одного и того же набора символов Unicode. UTF-16 был изобретен для поддержки кодовых точек выше U+FFFF, которые UCS-2 не может обрабатывать.

  4. Все UTF (в том числе многие из тех, которые вы не назвали) являются просто кодировками одного и того же набора символов Unicode. Число, указанное в имени, представляет собой количество битов, используемых в закодированных кодовых единицах (UTF-8 использует 8-битные кодовые единицы, UTF-16 использует 16-битные кодовые единицы и т. д.).

person Remy Lebeau    schedule 11.10.2017
comment
UTF-16 — это кодировка символов. UCS-2 — это набор символов. Когда началась работа над Windows NT, это было практически одно и то же. Численно, а не семантически. Различие не было таким уж важным до Windows 2000, как вы указываете в пунктах 2 и 3. - person IInspectable; 27.10.2017
comment
Приложения с поддержкой Unicode не используют кодовые страницы ANSI. Как включить поддержку Unicode в приложении? ничего не могу найти по этому поводу - person Barnack; 14.05.2019
comment
@Barnack, используя строки Unicode и API-интерфейсы Unicode в своем коде вместо использования строк ANSI и API-интерфейсов ANSI. Начните с того, что убедитесь, что ваш проект настроен на использование набора символов Unicode, чтобы во время компиляции были определены ``UNICODE` и _UNICODE условия, создавая все TCHAR/_TCHAR-based variables and C/Win32 APIs to use wchar_t` вместо char. Обратитесь к документации вашего компилятора для получения более подробной информации. - person Remy Lebeau; 14.05.2019
comment
@RemyLebeau wchar_t несколько лучше справляется с обработкой юникода только потому, что поддерживает до двух байтов. Это все еще не поддержка кодировки юникода. И это, безусловно, исключает utf-8, который вы должны использовать в программе, которая использует в основном западные строки, чтобы избежать потери памяти. - person Barnack; 14.05.2019
comment
@Barnack Вопрос ОП относится к Windows. А в Windows Unicode обрабатывается wchar_t и UTF-16. Хотя вы, безусловно, можете использовать UTF-8 в своем коде, если хотите, вам придется конвертировать в/из UTF-16 при взаимодействии с ОС. - person Remy Lebeau; 14.05.2019
comment
@RemyLebeau я говорю, что wchar_t просто обрабатывает 2-байтовые символы и будет работать для символов utf-16, которые занимают до 2 байтов. Не будет ли проблем у тех, кто берет больше? - person Barnack; 14.05.2019
comment
@Barnack Нет, потому что UTF-16 использует 2 16-битных значения (известных как суррогатная пара) для представления кодовых точек выше U + FFFF, и эти суррогаты идеально подходят для 2-байтовых wchar_ts. Это ничем не отличается от UTF-8, использующего более 1 8-битного char для представления кодовых точек выше U+007F. Все UTF поддерживают весь диапазон кодовых точек Unicode (U+0000..U+10FFFF). - person Remy Lebeau; 14.05.2019
comment
@RemyLebeau, так что в Windows wchar_t всегда интерпретируется как кодировка utf-16, в то время как char никогда не интерпретируется как utf-8, и нет никакого способа заставить ОС интерпретировать char как utf-8, я правильно понял? - person Barnack; 14.05.2019
comment
@Barnack wchar_t интерпретировался как UCS-2 до Windows 2000, но с 2000 года wchar_t теперь интерпретируется как UTF-16, да. Что касается char и UTF-8, большинство версий Windows не понимают UTF-8 (кроме нескольких отдельных случаев, таких как API MultiByteToWideChar()/WideCharToMultiByte(), расширения для fopen(), команда chmod консоли cmd и т. д.). Но в инсайдерской сборке Windows 10 17035 Microsoft, наконец, добавила поддержку кодовой страницы UTF-8 в устаревшие API-интерфейсы Win32 ANSI (т. е. для интерпретации строк char как UTF-8, а не как ANSI), но эта функция в настоящее время находится в стадии бета-тестирования. - person Remy Lebeau; 14.05.2019