হ্যাঁ, এটি হতাশ — কখনও কখনও type
এবং অন্যান্য প্রোগ্রামগুলি জিব্রিশ ছাপায় এবং কখনও কখনও তা করে না।
প্রথমত, ইউনিকোডের অক্ষরগুলি কেবল তখনই প্রদর্শিত হবে যদি বর্তমান কনসোল ফন্টে অক্ষর থাকে । সুতরাং ডিফল্ট রাস্টার ফন্টের পরিবর্তে লুসিডা কনসোলের মতো একটি ট্রু টাইপ ফন্ট ব্যবহার করুন।
তবে কনসোল ফন্টে আপনি যে অক্ষরটি প্রদর্শন করার চেষ্টা করছেন তা না থাকলে আপনি জিব্বারিশের পরিবর্তে প্রশ্ন চিহ্ন দেখতে পাবেন। আপনি যখন জিবিরশ হন, কেবল ফন্টের সেটিংসের চেয়ে আরও বেশি কিছু চলছে।
প্রোগ্রামগুলি যেমন স্ট্যান্ডার্ড সি-লাইব্রেরি I / O ফাংশনগুলি ব্যবহার করে printf
, প্রোগ্রামটির আউটপুট এনকোডিং অবশ্যই কনসোলের আউটপুট এনকোডিংয়ের সাথে মেলে , বা আপনি জিব্বারিশ পাবেন। chcp
বর্তমান কোডকেজ দেখায় এবং সেট করে। স্ট্যান্ডার্ড সি-লাইব্রেরি I / O ফাংশনগুলি ব্যবহার করে সমস্ত আউটপুট এমনভাবে আচরণ করা হয় যেন এটি প্রদর্শিত কোডকবেজে থাকে chcp
।
কনসোলের আউটপুট এনকোডিংয়ের সাথে প্রোগ্রামটির আউটপুট এনকোডিংটি মিলিয়ে দুটি ভিন্ন উপায়ে সম্পন্ন করা যেতে পারে:
কোনও প্রোগ্রাম কনসোলের বর্তমান কোডপেজ ব্যবহার করে chcp
বা এটি
ব্যবহার করে GetConsoleOutputCP
এবং সেটিকে এনকোডিংয়ে আউটপুটে কনফিগার করতে পারে, বা
আপনি বা কোনও প্রোগ্রাম প্রোগ্রামটির ডিফল্ট আউটপুট এনকোডিং ব্যবহার করে chcp
বা
কনসোলের বর্তমান কোডপেজ সেট করতে পারে setSetConsoleOutputCP
যাইহোক, উইন 32 এপিআই ব্যবহার করে এমন প্রোগ্রামগুলি ইউটিএফ-16LE স্ট্রিংগুলি সরাসরি কনসোলে লিখতে পারে
WriteConsoleW
। কোডপেজ সেট না করে সঠিক আউটপুট পাওয়ার একমাত্র উপায় এটি। এমনকি সেই ফাংশনটি ব্যবহার করার সময়ও, যদি কোনও স্ট্রিংটি শুরু করতে UTF-16LE এনকোডিংয়ে না থাকে, একটি উইন 32 প্রোগ্রামে অবশ্যই সঠিক কোডপেজটি পাস করতে হবে
MultiByteToWideChar
। এছাড়াও, WriteConsoleW
যদি প্রোগ্রামটির আউটপুট পুনঃনির্দেশিত হয় তবে কাজ করবে না; সেক্ষেত্রে আরও ফিডিং দরকার।
type
কিছু সময় কাজ করে কারণ এটি ইউটিএফ -16 এল বাইট অর্ডার মার্ক (বিওএম) , অর্থাৎ বাইটগুলির জন্য প্রতিটি ফাইলের সূচনা পরীক্ষা করে 0xFF 0xFE
। যদি এটি কোনও চিহ্ন খুঁজে পায় তবে এটি WriteConsoleW
বর্তমান কোডপেজ নির্বিশেষে ফাইলটিতে ইউনিকোড অক্ষর প্রদর্শন করে । তবে type
কোনও ইউটিএফ -১ B এলএইএম বিএম ছাড়াই কোনও ফাইল যখন ইনগ করার সময় বা অ্যাস্কিআই অক্ষর ব্যবহার না করে যে কোনও কমান্ড ব্যবহার করে না - 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 ফাইলটি একটি BOM মাধ্যমে কনসোলে মুদ্রিত সঙ্গে, হয় 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
ফাইলটির শুরুতে একটি কমান্ডের একটি ইউটিএফ-16LE বিওএম সনাক্ত করার জন্য যুক্তি রয়েছে এবং এটি মুদ্রণের জন্য বিশেষ উইন্ডোজ এপিআই ব্যবহার করে।
cmd.exe
এটি type
কোনও ফাইলের বাইরে যাওয়ার সময় আমরা একটি ডিবাগারে খোলার মাধ্যমে দেখতে পাই :
type
কোনও ফাইল খোলার পরে এটি আই-এর একটি বিওএম, লিটল-এন্ডিয়ান- 0xFEFF
এ বাইটগুলি পরীক্ষা
0xFF 0xFE
করে এবং যদি এরকম কোনও বিওএম থাকে তবে type
একটি অভ্যন্তরীণ fOutputUnicode
পতাকা সেট করে । কল করতে হবে কিনা তা সিদ্ধান্ত নিতে এই পতাকাটি পরে চেক করা হয়েছে WriteConsoleW
।
তবে type
ইউনিকোড আউটপুট পাওয়ার একমাত্র উপায় এটি এবং কেবলমাত্র সেই ফাইলগুলির জন্য যা বিওএম রয়েছে এবং ইউটিএফ -16 এল এ রয়েছে। অন্যান্য সমস্ত ফাইল এবং প্রোগ্রামগুলির জন্য যাদের কনসোল আউটপুট পরিচালনা করার জন্য বিশেষ কোড নেই, আপনার ফাইলগুলি বর্তমান কোডপেজ অনুসারে ব্যাখ্যা করা হবে এবং সম্ভবত গীব্রিশ হিসাবে প্রদর্শিত হবে।
আপনি 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
…
তবে, একটি সি প্রোগ্রাম যা একটি ইউনিকোড ইউটিএফ -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
আপনার বর্তমান কোডপেজ নির্বিশেষে কোনও বিওএম দিয়ে UTF-16LE ফাইল মুদ্রণ করতে পারে
- উইন 32 প্রোগ্রামগুলি ইউনিকোডকে কনসোলে আউটপুট দেওয়ার জন্য প্রোগ্রামিং করা যেতে পারে
WriteConsoleW
।
- অন্যান্য প্রোগ্রাম যা কোডপেজ সেট করে এবং ততক্ষণে তাদের আউটপুট এনকোডিং সামঞ্জস্য করে প্রোগ্রাম শুরু হওয়ার পরে কোডপেজটি কী ছিল তা নির্বিশেষে কনসোলটিতে ইউনিকোড প্রিন্ট করতে পারে
- অন্য সব কিছুর জন্য আপনাকে প্রায় গোলমাল করতে হবে
chcp
এবং সম্ভবত এখনও অদ্ভুত আউটপুট পাবে।