Windows で開くとcmd.exe
、どのようなエンコードが使用されますか?
現在使用されているエンコーディングを確認するにはどうすればいいですか?
地域設定に依存しますか、それとも確認すべき環境変数がありますか?
特定のエンコードでファイルを入力するとどうなりますか? 文字化けすることもあれば (エンコードが間違っているため)、うまく動作することもあります。
しかし、何が起こっているのか分からない限り、何も信用できません。誰か説明してもらえませんか?
ベストアンサー1
はい、イライラします。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 CON
Unicode が正しく表示されないという事実から、type
コマンドにはファイルの先頭にある UTF-16LE BOM を検出し、特別な Windows API を使用してそれを印刷するロジックがあると結論付けることができます。
ファイルの出力cmd.exe
時にデバッガーで開くと、これを確認できます。type
type
ファイルを開いた後、 の BOM (つまり、リトルエンディアンの0xFEFF
バイト)をチェックし、そのような BOM がある場合は内部フラグを設定します。このフラグは後で を呼び出すかどうかを決定するためにチェックされます。0xFF 0xFE
type
fOutputUnicode
WriteConsoleW
しかし、これは Unicode を出力する唯一の方法でありtype
、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
、おそらく依然として奇妙な出力が得られるでしょう。