Какая кодировка / кодовая страница является cmd.через ехе?
когда я открываю cmd.exe в Windows, какую кодировку он использует?
Как я могу проверить, какую кодировку он в настоящее время использует? Зависит ли это от моей региональной настройки или есть какие-либо переменные среды для проверки?
Что происходит при вводе файла с определенной кодировкой? Иногда я получаю искаженные символы (используется неправильная кодировка), а иногда это работает. Однако я не доверяю ничему, пока не знаю, что происходит. Кто-нибудь может объяснить?
5 ответов:
Да, это расстраивает-иногда
typeи другие программы печатают тарабарщину, а иногда и нет.во-первых, символы Юникода будут отображаться только если текущий шрифт консоли содержит символы. Так что используйте шрифт TrueType, такой как Lucida Console, вместо растрового шрифта по умолчанию.
но если шрифт консоли не содержит символ, который вы пытаетесь отобразить, вы увидите вопросительные знаки вместо тарабарщины. Когда вы получите тарабарщина, там происходит больше, чем просто настройки шрифта.
когда программы используют стандартные функции ввода-вывода библиотеки C, такие как
printf,в выходная кодировка программы должна соответствовать выходной кодировке консоли, или вы получите абракадабру.chcpпоказывает и задает текущую кодовую страницу. Все вывод с использованием стандартных функций ввода-вывода c-library обрабатывается так, как если бы он находился в кодовая страница отображается с помощьюchcp.сопоставление выходной кодировки программы с кодировкой консоли выходное кодирование может быть достигнуто двумя различными способами:
программа может получить текущую кодовую страницу консоли с помощью
chcpилиGetConsoleOutputCP, и настроить себя для вывода в этой кодировке, иливы или программа можете установить текущую кодовую страницу консоли с помощью
chcpилиSetConsoleOutputCPдля соответствия выходной кодировке программы по умолчанию.тем не менее, программы, которые использование Win32 API может писать строки UTF-16LE напрямую к консоли с помощью
WriteConsoleW. Это единственный способ получить правильный вывод без установки кодовых страниц. И даже при использовании этой функции, если строка не находится в кодировке UTF-16LE для начала программа Win32 должна передать правильную кодовую страницуMultiByteToWideChar. Кроме того,WriteConsoleWне будет работать, если вывод программы перенаправляется; в этом случае требуется больше скрипки.
typeработает некоторые из время, потому что он проверяет начало каждого файла для а UTF-16LE Метка Порядка Байтов (Спецификации), т. е. байт0xFF 0xFE. Если он найдет такой отметьте, он отображает символы Юникода в файле с помощьюWriteConsoleWнезависимо от текущей кодовой страницы. Но когдаtypeing любой файл без a UTF-16LE BOM, или для использования символов, отличных от ASCII, с любой командой это не вызовWriteConsoleW- вам нужно будет установить консольная кодовая страница и кодировка вывода программы для соответствия каждой другой.
как мы можем это узнать?
вот тестовый файл, содержащий символы в кодировке Unicode:
ASCII abcde xyz German äöü ÄÖÜ ß Polish ąęźżńł Russian абвгдеж эюя CJK 你好вот программа Java, чтобы распечатать тестовый файл в кучу разных кодировка Unicode. Это может быть на любом языке программирования; он только печатает Символы ASCII или закодированные байты в
stdout.import java.io.*; public class Foo { private static final String BOM = "\ufeff"; private static final String TEST_STRING = "ASCII abcde xyz\n" + "German äöü ÄÖÜ ß\n" + "Polish ąęźżńł\n" + "Russian абвгдеж эюя\n" + "CJK 你好\n"; public static void main(String[] args) throws Exception { String[] encodings = new String[] { "UTF-8", "UTF-16LE", "UTF-16BE", "UTF-32LE", "UTF-32BE" }; for (String encoding: encodings) { System.out.println("== " + encoding); for (boolean writeBom: new Boolean[] {false, true}) { System.out.println(writeBom ? "= bom" : "= no bom"); String output = (writeBom ? BOM : "") + TEST_STRING; byte[] bytes = output.getBytes(encoding); System.out.write(bytes); FileOutputStream out = new FileOutputStream("uc-test-" + encoding + (writeBom ? "-bom.txt" : "-nobom.txt")); out.write(bytes); out.close(); } } } }вывод в кодовой странице по умолчанию? полная фигня!
, что если мыZ:\andrew\projects\sx59084>chcp Active code page: 850 Z:\andrew\projects\sx59084>java Foo == UTF-8 = no bom ASCII abcde xyz German ├ñ├Â├╝ ├ä├û├£ ├ƒ Polish ─à─Ö┼║┼╝┼ä┼é Russian ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ CJK õ¢áÕÑ¢ = bom ´╗┐ASCII abcde xyz German ├ñ├Â├╝ ├ä├û├£ ├ƒ Polish ─à─Ö┼║┼╝┼ä┼é Russian ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ CJK õ¢áÕÑ¢ == UTF-16LE = no bom A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ♣☺↓☺z☺|☺D☺B☺ R u s s i a n 0♦1♦2♦3♦4♦5♦6♦ M♦N♦O♦ C J K `O}Y = bom ■A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ♣☺↓☺z☺|☺D☺B☺ R u s s i a n 0♦1♦2♦3♦4♦5♦6♦ M♦N♦O♦ C J K `O}Y == UTF-16BE = no bom A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣☺↓☺z☺|☺D☺B R u s s i a n ♦0♦1♦2♦3♦4♦5♦6 ♦M♦N♦O C J K O`Y} = bom ■ A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣☺↓☺z☺|☺D☺B R u s s i a n ♦0♦1♦2♦3♦4♦5♦6 ♦M♦N♦O C J K O`Y} == UTF-32LE = no bom A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ♣☺ ↓☺ z☺ |☺ D☺ B☺ R u s s i a n 0♦ 1♦ 2♦ 3♦ 4♦ 5♦ 6♦ M♦ N ♦ O♦ C J K `O }Y = bom ■ A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ♣☺ ↓☺ z☺ |☺ D☺ B☺ R u s s i a n 0♦ 1♦ 2♦ 3♦ 4♦ 5♦ 6♦ M♦ N ♦ O♦ C J K `O }Y == UTF-32BE = no bom A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣ ☺↓ ☺z ☺| ☺D ☺B R u s s i a n ♦0 ♦1 ♦2 ♦3 ♦4 ♦5 ♦6 ♦M ♦N ♦O C J K O` Y} = bom ■ A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣ ☺↓ ☺z ☺| ☺D ☺B R u s s i a n ♦0 ♦1 ♦2 ♦3 ♦4 ♦5 ♦6 ♦M ♦N ♦O C J K O` Y}typeфайлы, которые были сохранены? Они содержат точное те же байты, которые были напечатаны на консоли.Z:\andrew\projects\sx59084>type *.txt uc-test-UTF-16BE-bom.txt ■ A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣☺↓☺z☺|☺D☺B R u s s i a n ♦0♦1♦2♦3♦4♦5♦6 ♦M♦N♦O C J K O`Y} uc-test-UTF-16BE-nobom.txt A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣☺↓☺z☺|☺D☺B R u s s i a n ♦0♦1♦2♦3♦4♦5♦6 ♦M♦N♦O C J K O`Y} uc-test-UTF-16LE-bom.txt ASCII abcde xyz German äöü ÄÖÜ ß Polish ąęźżńł Russian абвгдеж эюя CJK 你好 uc-test-UTF-16LE-nobom.txt A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ♣☺↓☺z☺|☺D☺B☺ R u s s i a n 0♦1♦2♦3♦4♦5♦6♦ M♦N♦O♦ C J K `O}Y uc-test-UTF-32BE-bom.txt ■ A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣ ☺↓ ☺z ☺| ☺D ☺B R u s s i a n ♦0 ♦1 ♦2 ♦3 ♦4 ♦5 ♦6 ♦M ♦N ♦O C J K O` Y} uc-test-UTF-32BE-nobom.txt A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ☺♣ ☺↓ ☺z ☺| ☺D ☺B R u s s i a n ♦0 ♦1 ♦2 ♦3 ♦4 ♦5 ♦6 ♦M ♦N ♦O C J K O` Y} uc-test-UTF-32LE-bom.txt A S C I I a b c d e x y z G e r m a n ä ö ü Ä Ö Ü ß P o l i s h ą ę ź ż ń ł R u s s i a n а б в г д е ж э ю я C J K 你 好 uc-test-UTF-32LE-nobom.txt A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ♣☺ ↓☺ z☺ |☺ D☺ B☺ R u s s i a n 0♦ 1♦ 2♦ 3♦ 4♦ 5♦ 6♦ M♦ N ♦ O♦ C J K `O }Y uc-test-UTF-8-bom.txt ´╗┐ASCII abcde xyz German ├ñ├Â├╝ ├ä├û├£ ├ƒ Polish ─à─Ö┼║┼╝┼ä┼é Russian ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ CJK õ¢áÕÑ¢ uc-test-UTF-8-nobom.txt ASCII abcde xyz German ├ñ├Â├╝ ├ä├û├£ ├ƒ Polish ─à─Ö┼║┼╝┼ä┼é Russian ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ CJK õ¢áÕÑ¢The только то, что работает, - это файл UTF-16LE, с спецификацией, напечатанной на консоль через
type.если мы используем что-нибудь другое, чем
typeчтобы распечатать файл, то получится фигня:Z:\andrew\projects\sx59084>copy uc-test-UTF-16LE-bom.txt CON ■A S C I I a b c d e x y z G e r m a n õ ÷ ³ ─ Í ▄ ▀ P o l i s h ♣☺↓☺z☺|☺D☺B☺ R u s s i a n 0♦1♦2♦3♦4♦5♦6♦ M♦N♦O♦ C J K `O}Y 1 file(s) copied.из того, что
copy CONне отображает Юникод правильно, мы можем сделать вывод, чтоtypeкоманда имеет логику для обнаружения A UTF-16LE BOM at the запустите файл и используйте специальные API Windows для его печати.мы можем увидеть это, открыв
cmd.exeв отладчике, когда он идет кtypeиз файла:
после
typeоткрывает файл, он проверяет наличие спецификации0xFEFF-т. е. байт0xFF 0xFEв прямой и, если есть такая спецификация,typeустанавливает внутреннийfOutputUnicodeфлаг. Этот флаг проверяется позже, чтобы решить стоит ли звонитьWriteConsoleW.но это единственный способ получить
typeдля вывода Юникода, и только для файлов которые имеют BOMs и находятся в UTF-16LE. Для всех остальных файлов и программ что не имеют специального кода для обработки вывода консоли, ваши файлы будут интерпретируется в соответствии с текущей кодовой страницей и, скорее всего, будет отображаться как тарабарщина.вы можете эмулировать как
typeвыводит Unicode на консоль в ваших собственных программах, например:#include <stdio.h> #define UNICODE #include <windows.h> static LPCSTR lpcsTest = "ASCII abcde xyz\n" "German äöü ÄÖÜ ß\n" "Polish ąęźżńł\n" "Russian абвгдеж эюя\n" "CJK 你好\n"; int main() { int n; wchar_t buf[1024]; HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); n = MultiByteToWideChar(CP_UTF8, 0, lpcsTest, strlen(lpcsTest), buf, sizeof(buf)); WriteConsole(hConsole, buf, n, &n, NULL); return 0; }эта программа работает для печати Unicode в консоли Windows с помощью кодовая страница по умолчанию.
для примера Java-программы, мы можем получить немного правильный выход настройка кодовой страницы вручную, хотя выход получает перепутались странным образом:
Z:\andrew\projects\sx59084>chcp 65001 Active code page: 65001 Z:\andrew\projects\sx59084>java Foo == UTF-8 = no bom ASCII abcde xyz German äöü ÄÖÜ ß Polish ąęźżńł Russian абвгдеж эюя CJK 你好 ж эюя CJK 你好 你好 好 � = bom ASCII abcde xyz German äöü ÄÖÜ ß Polish ąęźżńł Russian абвгдеж эюя CJK 你好 еж эюя CJK 你好 你好 好 � == UTF-16LE = no bom A S C I I a b c d e x y z …тем не менее, программа C, которая устанавливает кодовую страницу Unicode UTF-8:
#include <stdio.h> #include <windows.h> int main() { int c, n; UINT oldCodePage; char buf[1024]; oldCodePage = GetConsoleOutputCP(); if (!SetConsoleOutputCP(65001)) { printf("error\n"); } freopen("uc-test-UTF-8-nobom.txt", "rb", stdin); n = fread(buf, sizeof(buf[0]), sizeof(buf), stdin); fwrite(buf, sizeof(buf[0]), n, stdout); SetConsoleOutputCP(oldCodePage); return 0; }есть правильный выход:
Z:\andrew\projects\sx59084>.\test ASCII abcde xyz German äöü ÄÖÜ ß Polish ąęźżńł Russian абвгдеж эюя CJK 你好
мораль этой истории?
typeможет печатать файлы UTF-16LE со спецификацией независимо от текущей кодовой страницы- программы Win32 можно запрограммировать для вывода Юникода на консоль, используя
WriteConsoleW.- другие программы, которые устанавливают кодовую страницу и соответственно настраивают свою кодировку вывода, могут печатать Unicode на консоли независимо от того, какая кодовая страница была при запуске программы
- для всего остального вам придется возиться с
chcp, и, вероятно, все еще будет странно выход.
тип
chcpчтобы увидеть текущую кодовую страницу (Как уже сказал Dewfy).
использовать
nlsinfoчтобы увидеть все установленные кодовые страницы и узнать, что означает номер вашей кодовой страницы.
вы должны иметь Windows Server 2003 Resource kit установлен (работает на Windows XP), чтобы использовать
nlsinfo.
чтобы ответить на ваш второй запрос re. как кодирование работает, Джоэл Спольски написал большой вводная статья об этом. Настоятельно рекомендованный.
команда CHCP показывает текущую кодовую страницу. Он имеет три цифры: 8xx и отличается от Windows 12xx. поэтому, набрав текст только на английском языке, вы не увидите никакой разницы, но расширенная кодовая страница (например, кириллица) будет напечатана неправильно.
Я долго расстраивался из-за проблем с кодовой страницей Windows, а также проблем с переносимостью и локализацией программ C, которые они вызывают. В предыдущих сообщениях подробно описаны проблемы, поэтому я не собираюсь ничего добавлять в этом отношении.
короче говоря, в конечном итоге я написал свой собственный уровень библиотеки совместимости UTF-8 поверх стандартной библиотеки Visual C++. В основном эта библиотека гарантирует, что стандартная программа C работает правильно, на любой кодовой странице, используя UTF-8 внутренне.
эта библиотека, называемая MsvcLibX, доступна с открытым исходным кодом по адресу https://github.com/JFLarvoire/SysToolsLib. основные характеристики:
- источники C, закодированные в UTF-8, используя обычные строки char[] C и стандартные API библиотеки C.
- на любой кодовой странице все обрабатывается внутренне как UTF-8 в вашем коде, включая основную () процедуру argv [], со стандартным вводом и выводом, автоматически преобразованным в правильный код страница.
- все stdio.H файловые функции поддерживают UTF-8 пути > 260 символов, до 64 Кбайт на самом деле.
- из тех же источников, может составить и успешно ссылке в Windows с использованием Visual C++ и MsvcLibX и библиотек Visual C++ в C, и в Linux, используя и стандартную библиотеку GCC и Linux на С++, без помощи #ifdef ... #за endif блоков.
- добавляет включить файлы, общие в Linux, но отсутствует в Visual C++. Например: unistd.h
- добавляет недостающие функции, как для ввода-вывода каталога, управления символическими ссылками и т. д., Все с поддержкой UTF-8, конечно :-).
Подробнее MsvcLibX README на GitHub, в том числе как построить библиотеку и использовать ее в своих собственных программах.
на раздел выпуска в приведенном выше репозитории GitHub предусмотрено несколько программ, использующих эту библиотеку MsvcLibX, что покажет ее возможности. Пример: попробуйте мой который.exe-инструмент с каталогами с именами, отличными от ASCII, в пути, поиск программ с именами, отличными от ASCII, и изменение кодовых страниц.
еще один полезный инструмент есть conv.exe программы. Эта программа может легко конвертировать поток данных с любой кодовой страницы на любую другую. По умолчанию он вводится на кодовой странице Windows, а выводится на текущей кодовой странице консоли. Это позволяет правильно просматривать данные, созданные графическими приложениями Windows (например, блокнот) в командной консоли, с помощью простой команды, такой как:
type WINFILE.txt | convэта библиотека MsvcLibX не является средства полные, и вклады для его улучшения приветствуются!

Comments