Evet, sinir bozucu - bazen type
ve diğer programlar anlamsız yazdırıyor, bazen de yazdırmıyor.
Her şeyden önce, Unicode karakterler yalnızca geçerli konsol yazı tipi karakter içeriyorsa görüntülenir . Bu nedenle, varsayılan Raster Yazı Tipi yerine Lucida Konsolu gibi bir TrueType yazı tipi kullanın.
Ancak konsol yazı tipi görüntülemeye çalıştığınız karakteri içermiyorsa anlamsızca soru işaretleri görürsünüz. Anlamsızlaştığınızda, yazı tipi ayarlarından daha fazlası olur.
Programları gibi standart C-kütüphane I / O fonksiyonlarını kullandığınızda printf
, programın çıkış kodlama Konsolun çıkış kodlamasını aynı olmalıdır , yoksa anlamsız olacaktır. chcp
geçerli kod sayfasını gösterir ve ayarlar. Standart C kitaplığı G / Ç işlevlerini kullanan tüm çıktılar, görüntülenen kod sayfasındaymış gibi işlenir chcp
.
Programın çıktı kodlamasını konsolun çıktı kodlamasıyla eşleştirmek iki farklı şekilde gerçekleştirilebilir:
Bir program chcp
veya
kullanarak konsolun geçerli kod sayfasını alabilir GetConsoleOutputCP
ve kendisini bu kodlamada çıkış yapacak şekilde yapılandırabilir veya
Siz veya bir program, programın varsayılan çıkış kodlamasını chcp
veya
SetConsoleOutputCP
ile eşleştirmek için konsolun geçerli kod sayfasını ayarlayabilirsiniz .
Ancak, Win32 API'leri kullanan programlar UTF-16LE dizelerini doğrudan konsola yazabilir
WriteConsoleW
. Kod sayfalarını ayarlamadan doğru çıktı almanın tek yolu budur. Ve bu işlevi kullanırken bile, başlangıçta UTF-16LE kodlamasında bir dize yoksa, bir Win32 programının doğru kod sayfasını geçmesi gerekir
MultiByteToWideChar
. Ayrıca, WriteConsoleW
programın çıktısı yeniden yönlendirilirse çalışmaz; bu durumda daha fazla uğraşmaya ihtiyaç vardır.
type
zaman zaman çalışır çünkü her dosyanın başlangıcını UTF-16LE Bayt Sırası İşareti (BOM) , yani bayt bakımından kontrol eder 0xFF 0xFE
. Böyle bir işaret bulursa WriteConsoleW
, geçerli kod sayfasından bağımsız olarak dosyadaki Unicode karakterlerini görüntüler . Ancak type
UTF-16LE BOM'su olmayan herhangi bir dosyayı ayarlarken veya çağırmayan herhangi bir komutla ASCII olmayan karakterler kullanırken WriteConsoleW
— konsol kod sayfasını ve program çıktı kodlamasını birbiriyle eşleşecek şekilde ayarlamanız gerekir.
Bunu nasıl bulabiliriz?
Unicode karakterleri içeren bir test dosyası:
ASCII abcde xyz
German äöü ÄÖÜ ß
Polish ąęźżńł
Russian абвгдеж эюя
CJK 你好
İşte test dosyasını bir dizi farklı Unicode kodlamasında yazdırmak için bir Java programı. Herhangi bir programlama dilinde olabilir; yalnızca ASCII karakterlerini veya kodlanmış baytları yazdırır 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();
}
}
}
}
Varsayılan kod sayfasındaki çıktı? Toplam çöp!
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}
Ancak, type
kaydedilen dosyalar biz olsaydı ? Konsola yazdırılanla aynı baytları içerirler.
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 õ¢áÕÑ¢
Çalışan tek şey, konsola BOM ile basılan UTF-16LE dosyasıdır type
.
type
Dosyayı yazdırmak dışında bir şey kullanırsak , çöp alırız:
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'u düzgün görüntülememesi gerçeğinden , type
komutun dosyanın başlangıcında bir UTF-16LE Malzeme Listesini tespit etmek için mantığı olduğu ve yazdırmak için özel Windows API'leri kullandığı sonucuna varabiliriz .
Bir dosya cmd.exe
çıktığında bir hata ayıklayıcıda açarak bunu görebiliriz type
:
type
Bir dosyayı açtıktan sonra , bir malzeme listesi ( 0xFEFF
yani, 0xFF 0xFE
küçük endiandaki baytlar
) olup olmadığını denetler ve böyle bir Malzeme Listesi varsa, type
dahili bir fOutputUnicode
bayrak ayarlar . Bu bayrak daha sonra aranıp aranmayacağına karar vermek için kontrol edilir WriteConsoleW
.
Ancak bu, type
Unicode çıktısını almanın tek yoludur ve yalnızca BOM'ları olan ve UTF-16LE'de olan dosyalar için. Diğer tüm dosyalar ve konsol çıktısını işlemek için özel kodu olmayan programlar için dosyalarınız geçerli kod sayfasına göre yorumlanacak ve muhtemelen anlamsız görünecektir.
Aşağıdaki type
gibi kendi programlarınızda Unicode'un konsola nasıl çıkış yaptığını taklit edebilirsiniz :
#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;
}
Bu program, varsayılan kod sayfasını kullanarak Windows konsolunda Unicode yazdırmak için çalışır.
Örnek Java programı için, kod sayfasını manuel olarak ayarlayarak biraz doğru çıktı alabiliriz, ancak çıktı garip yollarla berbat olur:
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
…
Ancak, Unicode UTF-8 kod sayfasını ayarlayan bir C programı:
#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;
}
doğru çıktıya sahip:
Z:\andrew\projects\sx\1259084>.\test
ASCII abcde xyz
German äöü ÄÖÜ ß
Polish ąęźżńł
Russian абвгдеж эюя
CJK 你好
Hikayenin ahlakı?
type
geçerli kod sayfanızdan bağımsız olarak bir Malzeme Listesiyle UTF-16LE dosyalarını yazdırabilir
- Win32 programları kullanarak Unicode konsoluna çıktı programlanabilir
WriteConsoleW
.
- Kod sayfasını ayarlayan ve çıkış kodlamasını buna göre ayarlayan diğer programlar, program başlatıldığında kod sayfasının ne olduğuna bakılmaksızın konsolda Unicode yazdırabilir
- Diğer her şey için uğraşmak zorunda
chcp
kalacaksınız ve muhtemelen tuhaf çıktı alacaksınız.