Czym jest strona kodująca/kodująca cmd.exe za pomocą?

Kiedy otwieram cmd.exe w Windows, jakiego kodowania używa?

Jak mogę sprawdzić, którego kodowania aktualnie używa? Czy zależy to od mojego ustawienia regionalnego, czy są jakieś zmienne środowiskowe do sprawdzenia?

Co się dzieje, gdy wpiszesz Plik z określonym kodowaniem? Czasami dostaję zniekształcone znaki (używane niepoprawne kodowanie), A czasami działa. Ale nie ufam nikomu, dopóki nie wiem, co się dzieje. Czy ktoś może to wyjaśnić?

Author: Peter Mortensen, 2009-08-11

5 answers

Tak, to frustrujące-czasami type i inne programy Drukuj bełkot, a czasami nie.

Po pierwsze, znaki Unicode będą wyświetlane tylko , jeśli bieżąca czcionka konsoli zawiera znaki . Więc użyj czcionka TrueType, taka jak Lucida Console, zamiast domyślnej czcionki rastrowej.

Ale jeśli czcionka konsoli nie zawiera znaku, który próbujesz wyświetlić, zobaczysz znaki zapytania zamiast bełkotu. Kiedy masz bełkot, jest więcej dalej niż tylko ustawienia czcionek.

Gdy programy używają standardowych funkcji We/Wy biblioteki C, takich jak printf, na kodowanie wyjściowe programu musi odpowiadać kodowaniu wyjściowemu konsoli , lub dostaniesz bełkotu. chcp pokazuje i ustawia bieżącą stronę kodową. Wszystkie wyjście przy użyciu standardowych funkcji We/Wy biblioteki C jest traktowane tak, jakby było w strona kodowa wyświetlana przez chcp.

Dopasowanie kodowania wyjściowego programu do kodowania wyjściowego konsoli można osiągnąć w dwóch różne sposoby:

  • Program może pobrać bieżącą stronę kodową konsoli za pomocą chcp lub GetConsoleOutputCP, i skonfigurować się do wyjścia w tym kodowaniu, lub

  • Ty lub program możesz ustawić bieżącą stronę kodową konsoli za pomocą chcp lub SetConsoleOutputCP aby dopasować domyślne kodowanie wyjściowe programu.

Jednak programy korzystające z API Win32 mogą pisać bezpośrednio ciągi UTF-16LE do konsoli z WriteConsoleW. To jest jedyny sposób, aby uzyskać poprawne wyjście bez ustawiania stron kodowych. Oraz nawet przy użyciu tej funkcji, jeśli ciąg znaków nie jest w kodowaniu UTF-16LE na początek Program Win32 musi przekazać poprawną stronę kodową do MultiByteToWideChar. Ponadto WriteConsoleW nie będzie działać, jeśli wynik programu zostanie przekierowany; w takim przypadku potrzeba więcej bałaganu.

type działa przez pewien czas, ponieważ sprawdza początek każdego pliku pod kątem UTF-16LE znak kolejności bajtów (BOM) , czyli bajty 0xFF 0xFE. Jeśli znajdzie taki znak, wyświetla znaki Unicode w pliku za pomocą WriteConsoleW niezależnie od aktualnej strony kodowej. Ale kiedy typeing dowolny plik bez UTF-16LE BOM, lub do używania znaków innych niż ASCII z dowolnym poleceniem to nie wywołuje WriteConsoleW - trzeba będzie ustawić kodowanie konsoli i kodowanie wyjścia programu, aby pasowały do siebie.


Jak możemy się tego dowiedzieć?

Oto testowy plik zawierający znaki Unicode:

ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好

Oto program Java do wydruku plik testowy w kilku różnych Kodowanie Unicode. Może być w dowolnym języku programowania; drukuje tylko Znaki ASCII lub zakodowane bajty do 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();
            }
        }
    }
}

Wyjście w domyślnej stronie kodowej? Totalna bzdura!

Z:\andrew\projects\sx\1259084>chcp
Active code page: 850

Z:\andrew\projects\sx\1259084>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}

Jednak, co jeśli type pliki, które zostały zapisane? Zawierają dokładnie te same bajty, które zostały wydrukowane na konsoli.

Z:\andrew\projects\sx\1259084>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       õ¢áÕÑ¢

tylko to co dziala to plik UTF-16LE, z BOM, wydrukowany na konsola via type.

Jeśli użyjemy czegoś innego niż type do wydrukowania pliku, otrzymamy śmieci:

Z:\andrew\projects\sx\1259084>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.

Z faktu, że copy CON nie wyświetla poprawnie Unicode, możemy wnioskować, że polecenie type ma logikę wykrywania BOM UTF-16LE w uruchom plik i użyj specjalnych interfejsów API systemu Windows, aby go wydrukować.

Możemy to zobaczyć otwierając cmd.exe w debuggerze, gdy przejdzie do type out a file:

Tutaj wpisz opis obrazka

Po otwarciu type plik sprawdza, czy BOM 0xFEFF - czyli bajty 0xFF 0xFE in little-endian-and if there is such a BOM, type sets an wewnętrzna fOutputUnicode flaga. Ta flaga jest sprawdzana później, aby zdecydować czy zadzwonić WriteConsoleW.

Ale to jedyny sposób, aby uzyskać type wyjście Unicode, i tylko dla plików które mają Bom i są w UTF-16LE. Dla wszystkich innych plików oraz dla programów które nie mają specjalnego kodu do obsługi wyjścia konsoli, Twoje pliki będą interpretowane zgodnie z aktualną stroną kodową i prawdopodobnie pojawi się jako bełkot.

Możesz emulować jak type wyprowadza Unicode do konsoli w swoich własnych programach jak tak:

#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;
}

Ten program działa do drukowania Unicode na konsoli Windows przy użyciu Domyślna strona kodowa.


Dla przykładowego programu Java, możemy uzyskać trochę poprawnego wyjścia przez w przeciwieństwie do poprzednich wersji, nie jest to możliwe.]}

Z:\andrew\projects\sx\1259084>chcp 65001
Active code page: 65001

Z:\andrew\projects\sx\1259084>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
…

Jednak program w C, który ustawia Unicode UTF-8 codepage:

#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;
}

Ma poprawne wyjście:

Z:\andrew\projects\sx\1259084>.\test
ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好

Morał tej historii?

  • Można drukować pliki UTF-16LE z BOM niezależnie od bieżącej strony kodowej]}
  • programy Win32 można zaprogramować tak, aby wyjście Unicode do konsoli, za pomocą WriteConsoleW.
  • inne programy, które ustawiają stronę kodową i odpowiednio dostosowują kodowanie wyjściowe, mogą drukować Unicode na konsoli, niezależnie od tego, jaka była strona kodowa, gdy program rozpoczęte
  • za wszystko inne będziesz musiał zadzierać chcp, i prawdopodobnie nadal będzie dziwnie wyjście.
 337
Author: andrewdotn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 05:34:15

Typ

chcp

Aby zobaczyć aktualną stronę kodu(jak już powiedział Dewfy).

Użyj

nlsinfo

Aby zobaczyć wszystkie zainstalowane strony kodowe i dowiedzieć się, co oznacza Twój numer strony kodowej.

Aby używać nlsinfo, musisz mieć zainstalowany System Windows Server 2003 Resource kit (działa na Windows XP).

 24
Author: Cagdas Altinkaya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-12 09:36:26

Aby odpowiedzieć na drugie zapytanie re. jak działa kodowanie, Joel Spolsky napisał świetny artykuł wprowadzający na ten temat . Zdecydowanie zalecane.

 21
Author: Brian Agnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-11 08:39:47

Polecenie CHCP pokazuje bieżącą stronę kodową. Ma trzy cyfry: 8xx i różni się od Windows 12xx. więc wpisując tekst tylko w języku angielskim nie zauważysz żadnej różnicy, ale Rozszerzona strona kodowa (jak Cyrylica) zostanie wydrukowana nieprawidłowo.

 5
Author: Dewfy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-12 08:35:58

Byłem sfrustrowany przez problemy ze stroną kodową systemu Windows oraz problemy z przenośnością i lokalizacją programów C, które powodują. Poprzednie posty szczegółowo opisywały kwestie, więc nie będę nic dodawać w tym zakresie.

Krótko mówiąc, w końcu napisałem własną warstwę biblioteki kompatybilności UTF-8 nad standardową biblioteką Visual C++. Zasadniczo ta Biblioteka zapewnia, że standardowy program C działa poprawnie, na dowolnej stronie kodowej, przy użyciu UTF-8 wewnętrznie.

Ta biblioteka, o nazwie MsvcLibX, jest dostępna jako open source pod adresem https://github.com/JFLarvoire/SysToolsLib . Główne cechy:

  • źródła C zakodowane w UTF-8, używając zwykłych łańcuchów znaków [] C i standardowych interfejsów API biblioteki C.
  • na dowolnej stronie kodowej wszystko jest przetwarzane wewnętrznie jako UTF-8 w kodzie, włączając w to funkcję main() argv [], ze standardowym wejściem i wyjściem automatycznie konwertowanym na właściwą stronę kodową.
  • Wszystkie stdio.plik h funkcje obsługują ścieżki UTF-8 > 260 znaków, w rzeczywistości do 64 Kb.
  • te same źródła mogą kompilować i łączyć się z powodzeniem w Windows przy użyciu Visual C++ i MsvcLibX i biblioteki Visual C++ C, a w Linuksie przy użyciu GCC i standardowej biblioteki C Linuksa, bez potrzeby stosowania # ifdef ... # endif blocks.
  • dodaje pliki nagłówkowe powszechne w Linuksie, ale brakujące w Visual C++. Ex: unistd.h
  • dodaje brakujące funkcje, takie jak te dla We/Wy katalogu, zarządzanie dowiązaniami symbolicznymi itp. Obsługa UTF-8 oczywiście: -).

Więcej szczegółów w MSVCLIBX README na GitHub , w tym jak zbudować bibliotekę i używać jej we własnych programach.

Sekcja release w powyższym repozytorium GitHub zawiera kilka programów korzystających z tej biblioteki MsvcLibX, które pokażą jej możliwości. Ex: spróbuj mojego, który.narzędzie exe z katalogami o nazwach innych niż ASCII w ścieżce, wyszukiwanie programów o nazwach innych niż ASCII i zmiana kodu stron.

Innym użytecznym narzędziem jest conv.program exe. Ten program może łatwo przekonwertować strumień danych z dowolnej strony kodowej na dowolną inną. Domyślnie jest to wejście na stronie kodowej systemu Windows, a wyjście na bieżącej stronie kodowej konsoli. Pozwala to na poprawne wyświetlanie danych generowanych przez aplikacje GUI systemu Windows (np. Notatnik) w konsoli poleceń, za pomocą prostego polecenia: type WINFILE.txt | conv

Ta biblioteka MsvcLibX w żadnym wypadku nie jest kompletna, a wkład w jej Ulepszanie jest mile widziany!

 1
Author: Jean-François Larvoire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-20 17:06:59