— Привіт, Аміго!

Зараз буде ще одна цікава тема – кодування.

Можливо, ти десь уже чув, що кожен символ має код (число). Саме тому тип char вважається не лише символьним, а й числовим типом.

Наприклад, код символу А англійського алфавіту – 65. B – 66, C – 67 і так далі. Свої коди є у великих літер і у маленьких, у російських літер, у китайських (ага, багато, багато кодів), цифр, різних символів – словом практично у всього, що можна назвати символом.

— Тобто. кожній літері чи кожному символу відповідає якесь число?

— Так, саме так.

Символ можна перетворити на число, а число на символ. Java взагалі практично не бачить різниці між ними:

char c = 'A'; //код(число) літери А – 65
c++; //Тепер містить число 66 – код літери B

— Цікаво.

— Так ось, кодуванням називається набір символів і відповідний набір кодів. Тільки таких кодувань вигадали не одне, а досить багато. А потім з'явилася універсальна – Unicode.

Хоча скільки б універсальних стандартів не придумали, від старих ніхто відмовлятися не поспішає. І все виходить прямо як на цій картинці:

Character, кодування - 1

Ось уяви, що Вася та Коля захотіли самостійно придумати кодування.

От кодування Васі:
Character, кодування - 2

А ось кодування Колі:
Character, кодування - 3

Вони навіть використовують ті самі символи, але коди у цих символів різні.

І ось коли рядок «ABC-123» у кодуванні Васі записують у файл, туди пишеться набір байт:
Character, кодування - 4

А тепер цей файл хоче прочитати іншу програму, яка використовує кодування Колі:

Ось що вона прочитає«345-IJK»

І найгірше те, що зазвичай ніде у файлі тип кодування не зберігається, і розробникам програм доводиться вгадувати їх.

— А як їх вгадувати?

— Це окрема тема. Але я хочу тобі розповісти, як працювати з кодуванням. Як ти вже знаєш, розмір типу char у Java – два байти. І рядки Java мають формат Unicode.

Але Java дозволяє перетворити рядок на набір байт будь-якого відомого кодування. Для цього є спеціальні методи класу String(!). Також Java має спеціальний клас Charset, який описує конкретне кодування.

1) Як отримати список усіх кодувань, з якими Java може працювати?

Для цього є спеціальний статичний метод доступнийCharsets. Цей метод повертає набір пар (ім'я кодування, об'єкт, що описує кодування)

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

У кожного кодування є унікальне ім'я, ось деякі з них: UTF-8, UTF-16, Windows-1251, KOI8-R,…

2) Як отримати поточне активне кодування (Unicode)?

Для цього є спеціальний метод defaultCharset

Charset currentCharset = Charset.defaultCharset();

3) Як перетворити рядок на певне кодування?

У Java на основі рядка можна створити масив байт у будь-якому відомому Java кодуванні:

Метод Приклад
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) А як перетворити набір байт, які я прочитав з файлу в рядок, якщо я знаю, в якому кодуванні вони були у файлі?

Тут все ще простіше – клас String має спеціальний конструктор:

Метод Приклад
String(byte bytes[])
byte[] buffer = new byte[1000];
inputStream.read(buffer);

String s = new String(buffer);
String(bytes byte[], Charset charset)< /pre>
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)< /pre>
byte[] buffer = new byte[1000];
inputStream.read(buffer);

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

5) А як перетворити набір байт з одного кодування на інше?

Є багато способів. Ось тобі один із найпростіших:

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);

— Я так і думав. Дякую за цікаву лекцію, Ріша.