Какая кодировка / кодовая страница является cmd.через ехе?



когда я открываю cmd.exe в Windows, какую кодировку он использует?



Как я могу проверить, какую кодировку он в настоящее время использует? Зависит ли это от моей региональной настройки или есть какие-либо переменные среды для проверки?



Что происходит при вводе файла с определенной кодировкой? Иногда я получаю искаженные символы (используется неправильная кодировка), а иногда это работает. Однако я не доверяю ничему, пока не знаю, что происходит. Кто-нибудь может объяснить?

870   5  

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 из файла:

enter image description here

после 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

    Ничего не найдено.