cmd.exeはどのエンコード/コードページを使用していますか?


271

Windowsでcmd.exeを開くと、どのエンコーディングを使用していますか?

現在使用しているエンコードを確認するにはどうすればよいですか?それは私の地域設定に依存しますか、それともチェックする環境変数がありますか?

特定のエンコーディングでファイルを入力するとどうなりますか?時々文字化けした文字(誤ったエンコーディングが使用されます)が表示され、場合によってはうまく機能します。しかし、何が起こっているのかわからない限り、私は何も信用しません。誰か説明できますか?

回答:


389

はい、それはイライラします—時々typeおよび他のプログラムは意味不明なものを印刷し、時には彼らはしません。

まず、Unicode文字は、現在のコンソールフォントに文字が含まれている場合にのみ表示されます。したがって、デフォルトのラスターフォントではなく、Lucida ConsoleのようなTrueTypeフォントを使用してください。

ただし、コンソールフォントに表示しようとしている文字が含まれていない場合は、意味不明な文字ではなく疑問符が表示されます。意味不明になったら、フォントの設定だけではありません。

プログラムは以下のように、標準CライブラリI / O関数を使用するとprintfプログラムの出力エンコーディングは、コンソールの出力エンコーディングと一致する必要があります、またはあなたはちんぷんかんぷんを取得します。chcp現在のコードページを表示および設定します。標準のCライブラリI / O関数を使用するすべての出力は、によって表示されるコードページにあるかのように扱われますchcp

プログラムの出力エンコーディングとコンソールの出力エンコーディングを一致させるには、次の2つの方法があります。

  • プログラムは、chcpまたは を使用してコンソールの現在のコードページを取得し、GetConsoleOutputCPそのエンコーディングで出力するようにプログラム自体を構成できます。

  • ユーザーまたはプログラムは、chcpまたは SetConsoleOutputCPを使用してコンソールの現在のコードページを設定し、プログラムのデフォルトの出力エンコーディングと一致させることができます。

ただし、Win32 APIを使用するプログラムは、を使用してUTF-16LE文字列をコンソールに直接書き込むことができます WriteConsoleW。これは、コードページを設定せずに正しい出力を得る唯一の方法です。また、その関数を使用する場合でも、文字列が最初からUTF-16LEエンコーディングになっていない場合、Win32プログラムは正しいコードページをに渡す必要があります MultiByteToWideChar。また、WriteConsoleWプログラムの出力がリダイレクトされている場合は機能しません。その場合はもっといじる必要があります。

typeは、各ファイルの先頭でUTF-16LE バイトオーダーマーク(BOM)、つまりバイトをチェックするため、ときどき動作します0xFF 0xFE。そのようなマークが見つかるWriteConsoleW と、現在のコードページに関係なく、ファイル内のUnicode文字が表示されます。ただしtype、UTF-16LE BOMのないファイルを呼び出す場合、または呼び出しを行わないコマンドで非ASCII文字を使用WriteConsoleWする場合は、コンソールのコードページとプログラムの出力エンコーディングを互いに一致するように設定する必要があります。


どうすればこれを見つけることができますか?

Unicode文字を含むテストファイルを次に示します。

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

これは、さまざまなUnicodeエンコーディングの束でテストファイルを印刷するJavaプログラムです。任意のプログラミング言語で作成できます。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\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}

しかし、type保存されたファイルがどうなるのでしょうか?それらは、コンソールに出力されたものとまったく同じバイトを含みます。

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       õ¢áÕÑ¢

唯一の事は動作することを経由してコンソールに出力BOM、で、UTF-16LEファイルですtype

typeファイルの印刷以外に何かを使用すると、ゴミが発生します。

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.

copy CONUnicodeが正しく表示されないという事実から、typeコマンドにはファイルの先頭でUTF-16LE BOMを検出するロジックがあり、特別なWindows APIを使用してそれを印刷することができます。

これを確認するにcmd.exeは、デバッガーでtype ファイルを開くときに開きます。

ここに画像の説明を入力してください

typeファイルを開いた後、BOM 0xFEFF(つまり、0xFF 0xFEリトルエンディアンのバイト) をチェックし、そのようなBOMがある場合typeは、内部fOutputUnicodeフラグを設定します。このフラグは後でチェックされ、を呼び出すかどうかを決定しますWriteConsoleW

しかし、それがtypeUnicodeを出力する唯一の方法であり、BOMがあり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;
}

このプログラムは、デフォルトのコードページを使用してWindowsコンソールでUnicodeを印刷するために機能します。


サンプルJavaプログラムの場合、コードページを手動で設定することにより、少し正しい出力を得ることができますが、出力は奇妙な方法で混乱します。

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
…

ただし、Unicode UTF-8コードページを設定するCプログラム:

#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\sx\1259084>.\test
ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好

物語の教訓?

  • type 現在のコードページに関係なく、BOMを使用してUTF-16LEファイルを印刷できます
  • Win32プログラムは、を使用して、Unicodeをコンソールに出力するようにプログラムできます WriteConsoleW
  • コードページを設定し、それに応じて出力エンコーディングを調整する他のプログラムは、プログラムの開始時のコードページに関係なく、コンソールにUnicodeを印刷できます。
  • それ以外の場合は、をいじる必要がありchcp、おそらく変な出力が得られます。

73
おっと、これは私がSOでこれまで見た中で最も詳細な答えでなければなりません。派手なプリントと多言語スキルの追加クレジット!ただ美しい、先生!
2013年

2
また、VS2008で導入されたMicrosoft固有の拡張機能_setmode(_fileno(stdout)、_O_U16TEXT)を検討することもできます。参照stackoverflow.com/a/9051543、およびstackoverflow.com/a/12015918を、そしてmsdn.microsoft.com/en-us/library/tw4k6df8(v=vs.90).aspx)(_setmodeの間に明確な移植性の違いのほかにとSetConsoleOutputCP()では、一見すると完全には理解されていない、両方のアプローチに他の微妙な点や副作用が隠されている可能性もあります。andrewdotnが_setmode(fd、_O_U16TEXT)に関する観察で彼の回答を更新できれば、それは素晴らしいことです。
JasDev 2014

13
これは素晴らしい答えですが、コンソールがUTF-16をサポートしていると誤解を招く恐れがあります。これはUCS-2に制限されています。つまり、基本的な多言語プレーン(BMP)の文字に制限されています。Win32コンソールサーバー(conhost.exe、現在)が1990年頃に設計されたとき、Unicodeは16ビット標準であったため、コンソール画面バッファーは文字セルごとに1つの16ビットWCHARを使用します。UTF-16サロゲートペアは、2つのボックス文字として印刷されます。
Eryk Sun、2015

3
@ user200783、分解されたフォームはサポートされていません。通常、NFCの同等のものに変換できます。また、西欧ロケールのコンソールでは、全角と半角のグリフを混在させることはできません。また、コードページ65001(UTF-8)を使用している場合、Windows 8より前WriteFileでは、バイト数ではなく書き込まれた文字数が報告されるため、バッファーライターは「残りの」バイトを非ASCII文字数に比例して数回再試行します。 。また、65001では、を呼び出すときにUTF-16コードごとに1 ANSIバイトを想定するため、conhost.exeで非ASCII文字の読み取りが失敗しWideCharToMultiByteます。
Eryk Sun 2016

2
この回答の簡単なデモプログラムはGetStdHandle(STD_OUTPUT_HANDLE)、C stdoutがコンソールハンドルであることを前提としています。実際には、コンソールをテストするには、それGetConsoleModeが成功することを確認します。また、Cランタイム_isatty関数を使用して、低I / Oファイル記述子がコンソールかどうかを確認しないでください。これは、文字モードデバイス(NUL他のものを含む)をチェックするだけです。代わりに、_get_osfhandle直接呼び出してハンドルを確認してください。
Eryk Sun、

29

タイプ

chcp

(Dewfyが既に言ったように)現在のコードページを表示します。

使用する

nlsinfo

インストールされているすべてのコードページを確認し、コードページ番号の意味を確認します。

を使用するには、Windows Server 2003リソースキットをインストールする必要があります(Windows XPで動作)nlsinfo


19
興味深いことに、nlsinfo私のWindows 7には存在しないようです
Joey、

2
nlsinfo私のWindows XP SP3マシンにも存在しません。
Thomas Owens

2
あっ、すみません。Windows Server Resource Kitツールに付属していると思います。以前にWindows XP SP3マシンで数回使用したことがあり、デフォルトでインストールされていないことを知りませんでした。
Cagdas Altinkaya、2009

ああ、それがなぜ私がそれらをインストールしたVistaマシンにあるのかを説明しています。
ジョーイ

4
nlsinfoWindows 10Eマシンにも存在しません。
Yousha Aleayoub

21

2番目のクエリに再回答します。エンコーディングがどのように機能するかについて、Joel Spolskyはこれに関するすばらしい紹介記事を書きました。強く推奨する。


13
私はそれを読み、それを知っています。ただし、Windowsでは、OSとほとんどのアプリケーションがエンコーディングをまったく知らないように見えるため、いつも迷っています。
danglund 2009

5

コマンドCHCPは現在のコードページを表示します。3桁:8xxで、Windows 12xxとは異なります。したがって、英語のみのテキストを入力しても違いはありませんが、拡張コードページ(キリル文字など)が誤って印刷されます。


5
CHCPでは3桁しか表示されず、8 ##形式でも表示されません。たとえば、437はUSエンコーディングであり、英語システムのデファクトスタンダードです。-65001はUnicodeエンコーディング(私が正しく思い出せばUTF-8で65000はUTF-7です)であり、選択できます。また、CMDでは、たとえば1250コードページに切り替えることができますが、これらのコードページがいつ選択可能になるかわかりません。(Win7の下にあります。)
Adam LS

4

Windowsコードページの問題と、Cプログラムの移植性とローカリゼーションの問題が原因で、私は長い間イライラしてきました。以前の投稿では問題を詳細に説明しているため、この点については何も追加しません。

長い話を簡単にするために、結局私はVisual C ++標準Cライブラリーの上に自分のUTF-8互換性ライブラリー層を作成することになりました。基本的にこのライブラリは、UTF-8を内部で使用して、標準のCプログラムがどのコードページでも正しく機能することを保証します。

MsvcLibXと呼ばれるこのライブラリは、https://github.com/JFLarvoire/SysToolsLibでオープンソースとして入手できます。主な特徴:

  • 通常のchar [] C文字列と標準CライブラリAPIを使用して、UTF-8でエンコードされたCソース。
  • どのコードページでも、main()ルーチンargv []を含め、コード内ではすべてがコード内でUTF-8として内部的に処理され、標準入出力が正しいコードページに自動的に変換されます。
  • すべてのstdio.hファイル関数は、260文字を超えるUTF-8パス名、実際には最大64 KBをサポートします。
  • 同じソースは、WindowsではVisual C ++およびMsvcLibXとVisual C ++ Cライブラリを使用してコンパイルおよびリンクでき、LinuxではgccおよびLinux標準Cライブラリを使用して、#ifdef ... #endifブロックを必要としません。
  • Linuxで一般的なインクルードファイルを追加しますが、Visual C ++にはありません。例:unistd.h
  • もちろん、ディレクトリI / O、シンボリックリンク管理などの不足している関数をすべてUTF-8サポート付きで追加します:-)。

GitHubMsvcLibX READMEに詳細が記載されています。これには、ライブラリを構築して独自のプログラムで使用する方法が含まれます。

上記のGitHubリポジトリのリリースセクションには、このMsvcLibXライブラリを使用するいくつかのプログラムがあり、その機能を示します。例:PATHに非ASCII名のディレクトリがあるmy.exeツールを試し、非ASCII名のプログラムを検索し、コードページを変更します。

そこに別の便利なツールはconv.exeプログラムです。このプログラムは、データストリームを任意のコードページから任意のコードページに簡単に変換できます。デフォルトは、Windowsコードページでの入力で、現在のコンソールコードページでの出力です。これにより、次のような簡単なコマンドを使用して、Windows GUIアプリ(メモ帳など)によって生成されたデータをコマンドコンソールで正しく表示できます。type WINFILE.txt | conv

このMsvcLibXライブラリは完全ではありません。ライブラリを改善するための貢献を歓迎します!


2

Javaでは、「IBM850」というエンコーディングを使用してファイルを記述しました。それで問題は解決しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.