"Chào, Amigo!"

"Bây giờ là lúc cho một chủ đề thú vị khác: mã hóa."

"Có lẽ bạn đã nghe ở đâu đó rằng mỗi ký tự đều có một mã (số). Đó là lý do tại sao loại char có thể biểu thị cả ký hiệu và số."

"Ví dụ: mã của chữ 'A' trong bảng chữ cái tiếng Anh là 65. 'B' là 66, 'C' là 67, v.v. Có các mã duy nhất cho chữ hoa, chữ thường, chữ Cyrillic, tiếng Trung ký tự (vâng, rất nhiều mã), số và các ký hiệu khác nhau. Tóm lại, thực tế có một mã cho mọi thứ mà bạn gọi là ký tự."

"Vì vậy, mỗi chữ cái và ký tự tương ứng với một số?"

"Đúng."

"Một ký tự có thể được chuyển đổi thành một số và một số thành một ký tự. Java thường không thấy sự khác biệt giữa chúng:"

char c = 'A'; //The code (number) for 'A' is 65
c++; //Now c contains the number 66, which is the code for 'B'

"Hấp dẫn."

"Vì vậy, một mã hóa là một tập hợp các ký hiệu và bộ mã tương ứng của chúng. Nhưng không chỉ một mã hóa đã được phát minh - có khá nhiều mã hóa. Mãi sau này, một mã hóa phổ biến, Unicode, mới được phát minh."

"Nhưng cho dù có bao nhiêu tiêu chuẩn phổ quát được phát minh ra, thì cũng không ai vội từ bỏ những tiêu chuẩn cũ. Và rồi mọi thứ diễn ra giống như trong phim hoạt hình này:"

Bảng mã ký tự - 1

"Hãy tưởng tượng rằng Vincent và Nick quyết định tạo mã hóa của riêng họ."

"Đây là mã hóa của Vincent:"
Bảng mã ký tự - 2

"Và đây là mã hóa của Nick:"
Bảng mã ký tự - 3

"Họ thậm chí sử dụng các ký tự giống nhau, nhưng mã cho các ký tự lại khác nhau."

"Khi chuỗi 'ABC-123' được ghi vào một tệp bằng mã hóa của Vincent, chúng tôi nhận được tập hợp byte sau:"
Bảng mã ký tự - 4

"Và bây giờ một chương trình khác sử dụng mã hóa của Nick muốn đọc tệp:"

"Đây là nội dung: «345-IJK»."

"Và điều tồi tệ nhất là mã hóa thường không được lưu trữ ở bất kỳ đâu trong tệp, vì vậy các nhà phát triển phải đoán."

"Chà, làm thế nào để họ đoán chúng?"

"Đó là một chủ đề khác. Nhưng tôi muốn giải thích cách làm việc với mã hóa. Như bạn đã biết, kích thước của một ký tự trong Java là hai byte. Và Chuỗi Java sử dụng định dạng Unicode."

"Nhưng Java cho phép bạn chuyển đổi một Chuỗi thành một tập hợp các byte trong bất kỳ mã hóa nào mà nó biết. Lớp Chuỗi có các phương thức đặc biệt cho việc này. Java cũng có một lớp Charset đặc biệt mô tả một mã hóa cụ thể."

1) Làm cách nào để có danh sách tất cả các mã hóa mà Java hỗ trợ?

"Có một phương thức tĩnh đặc biệt được gọi là availableCharsets dành cho điều đó. Phương thức này trả về một tập hợp các cặp (tên mã hóa, đối tượng mô tả mã hóa):"

SortedMap<String,Charset> charsets = Charset.availableCharsets();

"Mỗi mã hóa có một tên duy nhất. Dưới đây là một số mã hóa: UTF-8, UTF-16, Windows-1251, KOI8-R,..."

2) Làm cách nào để tôi có được mã hóa hoạt động hiện tại (Unicode)?

"Có một phương pháp đặc biệt gọi là defaultCharset cho điều đó.

Charset currentCharset = Charset.defaultCharset();

3) Làm cách nào để chuyển đổi Chuỗi thành mã hóa cụ thể?

"Trong Java, bạn có thể chuyển đổi một Chuỗi thành một mảng byte trong bất kỳ mã hóa nào mà Java biết:"

Phương pháp Ví dụ
byte[] getBytes()
String s = "Good news, everyone!";
byte[] buffer = s.getBytes()
byte[] getBytes(Charset charset)
String s = "Good news, everyone!";
Charset koi8 = Charset.forName("KOI8-R");
byte[] buffer = s.getBytes(koi8);
byte[] getBytes(String charsetName)
String s = "Good news, everyone!";
byte[] buffer = s.getBytes("Windows-1251")

4) Làm cách nào để chuyển đổi một mảng byte mà tôi đã đọc từ tệp thành Chuỗi, nếu tôi biết mã hóa của nó trong tệp là gì?

"Điều này thậm chí còn dễ dàng hơn. Lớp String có một hàm tạo đặc biệt:"

Phương pháp Ví dụ
String(byte bytes[])
byte[] buffer = new byte[1000];
inputStream.read(buffer);

String s = new String(buffer);
String(byte bytes[], Charset charset)
byte[] buffer = new byte[1000];
inputStream.read(buffer);

Charset koi8 = Charset.forName("KOI8-R");
String s = new String(buffer, koi8);
String(byte bytes[], String charsetName)
byte[] buffer = new byte[1000];
inputStream.read(buffer);

String s = new String(buffer, "Windows-1251");

5) Làm cách nào để chuyển đổi một mảng byte từ mã hóa này sang mã hóa khác?

"Có nhiều cách. Đây là một trong những cách đơn giản nhất:"

Charset koi8 = Charset.forName("KOI8-R");
Charset windows1251 = Charset.forName("Windows-1251");

byte[] buffer = new byte[1000];
inputStream.read(buffer);
String s = new String(buffer, koi8);
buffer = s.getBytes(windows1251);
outputStream.write(buffer);

"Đó là những gì tôi nghĩ. Cảm ơn vì bài học thú vị, Rishi."