हां, यह निराशाजनक है- कभी-कभी type
और अन्य कार्यक्रम अस्पष्ट होते हैं, और कभी-कभी वे नहीं करते हैं।
सबसे पहले, यूनिकोड वर्ण केवल प्रदर्शित करेगा यदि वर्तमान कंसोल फ़ॉन्ट में वर्ण हैं । इसलिए डिफ़ॉल्ट Raster फ़ॉन्ट के बजाय Lucida Console जैसे ट्रू टाइप फ़ॉन्ट का उपयोग करें।
लेकिन यदि कंसोल फ़ॉन्ट में वह चरित्र नहीं है जिसे आप प्रदर्शित करने का प्रयास कर रहे हैं, तो आपको जिबरिश के बजाय प्रश्न चिह्न दिखाई देंगे। जब आप अस्पष्ट हो जाते हैं, तो फॉन्ट सेटिंग्स की तुलना में अधिक चल रहा है।
जब प्रोग्राम मानक सी-लाइब्रेरी I / O फ़ंक्शन का उपयोग करते हैं printf
, जैसे कि प्रोग्राम का आउटपुट एन्कोडिंग कंसोल के आउटपुट एन्कोडिंग से मेल खाना चाहिए , या आपको जीब्रीश मिलेगा। chcp
वर्तमान कोडपृष्ठ दिखाता और सेट करता है। मानक सी-लाइब्रेरी I / O फ़ंक्शन का उपयोग करने वाले सभी आउटपुट को इस तरह से व्यवहार किया जाता है जैसे कि यह प्रदर्शित किए गए कोडपेज में है chcp
।
कंसोल के आउटपुट एन्कोडिंग के साथ प्रोग्राम के आउटपुट एन्कोडिंग का मिलान दो अलग-अलग तरीकों से किया जा सकता है:
एक प्रोग्राम कंसोल के वर्तमान कोडपेज का उपयोग करके chcp
या
GetConsoleOutputCP
उस एन्कोडिंग में आउटपुट के लिए कॉन्फ़िगर कर सकता है, या
आप या प्रोग्राम का उपयोग करके chcp
या
SetConsoleOutputCP
प्रोग्राम के डिफ़ॉल्ट आउटपुट एन्कोडिंग से मिलान करने के लिए कंसोल के वर्तमान कोडपेज को सेट कर सकते हैं ।
हालाँकि, Win32 API का उपयोग करने वाले प्रोग्राम UTF-16LE स्ट्रिंग्स को सीधे कंसोल से लिख सकते हैं
WriteConsoleW
। कोडपे को सेट किए बिना सही आउटपुट प्राप्त करने का यह एकमात्र तरीका है। और उस फ़ंक्शन का उपयोग करते समय, यदि कोई स्ट्रिंग UTF-16LE एन्कोडिंग के साथ शुरू करने के लिए नहीं है, तो Win32 प्रोग्राम को सही कोडपेज को पास करना होगा
MultiByteToWideChar
। इसके अलावा,WriteConsoleW
कार्यक्रम के आउटपुट को पुनर्निर्देशित करने पर काम नहीं करेगा; उस मामले में और अधिक निपुणता की आवश्यकता है।
type
कुछ समय के लिए काम करता है क्योंकि यह UTF-16LE बाइट ऑर्डर मार्क (BOM) के लिए प्रत्येक फ़ाइल की शुरुआत की जाँच करता है , यानी बाइट्स 0xFF 0xFE
। यदि यह ऐसा चिह्न पाता है, तो यह WriteConsoleW
वर्तमान कोडपेज की परवाह किए बिना फ़ाइल में यूनिकोड वर्ण प्रदर्शित करता है । लेकिन जब type
कोई फ़ाइल बिना UTF-16LE BOM के या किसी भी कमांड के साथ गैर-ASCII वर्णों का उपयोग करने के लिए जो कॉल नहीं करता है, तो WriteConsoleW
आपको एक-दूसरे से मिलान करने के लिए कंसोल कोडपेज और प्रोग्राम आउटपुट एन्कोडिंग सेट करने की आवश्यकता होगी।
हम इसका पता कैसे लगा सकते हैं?
यहां एक परीक्षण फ़ाइल है जिसमें यूनिकोड वर्ण हैं:
ASCII abcde xyz
German äöü ÄÖÜ ß
Polish ąęźżńł
Russian абвгдеж эюя
CJK 你好
विभिन्न यूनिकोड एनकोडिंग के एक समूह में परीक्षण फ़ाइल को प्रिंट करने के लिए यहां जावा प्रोग्राम है। यह किसी भी प्रोग्रामिंग भाषा में हो सकता है; यह केवल 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 õ¢áÕÑ¢
केवल बात यह है कि काम करता है 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
यूनिकोड को सही ढंग से प्रदर्शित नहीं किया गया है, हम यह निष्कर्ष निकाल सकते हैं कि type
कमांड में फ़ाइल की शुरुआत में UTF-16LE BOM का पता लगाने के लिए तर्क है, और इसे प्रिंट करने के लिए विशेष विंडोज एपीआई का उपयोग करें।
हम cmd.exe
इसे डिबगर में खोलकर देख सकते हैं जब यह type
एक फ़ाइल को बाहर जाता है :
type
एक फ़ाइल खोलने के बाद , यह एक बीओआई के लिए जाँच करता है 0xFEFF
, 0xFF 0xFE
थोड़ा-एंडियन में बाइट्स
- और अगर ऐसा कोई बॉम है, तो type
एक आंतरिक fOutputUnicode
ध्वज सेट करता है । यह ध्वज बाद में जांचा जाता है कि क्या कॉल करना है WriteConsoleW
।
लेकिन यह type
यूनिकोड को प्राप्त करने का एकमात्र तरीका है , और केवल उन फ़ाइलों के लिए जिनके पास BOMs हैं और UTF-16LE में हैं। अन्य सभी फ़ाइलों के लिए, और उन प्रोग्रामों के लिए, जिनके पास कंसोल आउटपुट को संभालने के लिए विशेष कोड नहीं है, आपकी फ़ाइलों की वर्तमान कोडपेज के अनुसार व्याख्या की जाएगी, और संभवतः यह अस्पष्ट रूप में दिखाई देगा।
आप अनुकरण कर सकते हैं कि type
यूनिकोड को अपने स्वयं के कार्यक्रमों में कंसोल के लिए कैसे आउटपुट करता है:
#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;
}
यह प्रोग्राम डिफ़ॉल्ट कोडपेज का उपयोग करके विंडोज कंसोल पर यूनिकोड को प्रिंट करने के लिए काम करता है।
नमूना जावा प्रोग्राम के लिए, हम कोडपेज को मैन्युअल रूप से सेट करके थोड़ा सही आउटपुट प्राप्त कर सकते हैं, हालांकि आउटपुट अजीब स्थिति में गड़बड़ हो जाता है:
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
…
हालाँकि, एक C प्रोग्राम जो यूनिकोड 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\sx\1259084>.\test
ASCII abcde xyz
German äöü ÄÖÜ ß
Polish ąęźżńł
Russian абвгдеж эюя
CJK 你好
कहानी का नैतिक पहलू है?
type
अपने वर्तमान कोड पृष्ठ की परवाह किए बिना BOM के साथ UTF-16LE फ़ाइलों को प्रिंट कर सकते हैं
- Win32 प्रोग्राम को यूनिकोड को कंसोल में आउटपुट करने के लिए प्रोग्राम किया जा सकता है, का उपयोग करके
WriteConsoleW
।
- अन्य प्रोग्राम जो कोडपेज को सेट करते हैं और तदनुसार अपने आउटपुट एन्कोडिंग को समायोजित करते हैं, इस बात की परवाह किए बिना कि कोडपेज क्या था, तब यूनिकोड को कंसोल पर प्रिंट कर सकते हैं।
- बाकी सभी चीजों के लिए आपको गड़बड़ करना
chcp
होगा, और शायद अभी भी अजीब आउटपुट मिलेगा।