— Привет, Амиго!
Сейчас будет еще одна интересная тема – кодировки.
Возможно, ты где-то уже слышал, что у каждого символа есть код (число). Именно поэтому тип char считается не только символьным, но и числовым типом.
Например код символа А английского алфавита – 65. B – 66, C – 67и так далее. Свои коды есть у больших букв и у маленьких, у русских букв, у китайских (ага, много, много кодов), у цифр, у различных символов – словом практически у всего, что можно назвать символом.
— Т.е. каждой букве или каждому символу соответствует какое-то число?
— Да, именно так.
Символ можно преобразовать в число, а число в символ. Java вообще практически не видит разницы между ними:
char c = 'A'; //код(число) буквы А – 65
c++; //Теперь с содержит число 66 – код буквы B
— Интересно.
— Так вот, кодировкой называется набор символов и соответствующий им набор кодов. Только таких кодировок придумали не одну, а достаточно много. А потом появилась универсальная – Unicode.
Хотя, сколько бы универсальных стандартов не придумали, от старых никто отказываться не спешит. И все получается прямо как на этой картинке:

Вот представь, что Вася и Коля захотели самостоятельно придумать кодировки.
Вот кодировка Васи:
А вот кодировка Коли:
Они даже используют одни и те же символы, но коды у этих символов разные.
И вот когда строку «ABC-123» в кодировке Васи записывают в файл, туда пишется набор байт:
А теперь этот файл хочет прочитать другая программа, которая использует кодировку Коли:
Вот что она прочитает«345-IJK»
И самое плохое то, что обычно нигде в файле тип кодировки не хранится, и разработчикам программ приходится угадывать их.
— А как их угадывать?
— Это отдельная тема. Но я хочу тебе рассказать, как работать с кодировками. Как ты уже знаешь, размер типа char в Java – два байта. И строки в Java имеют формат Unicode.
Но Java позволяет преобразовать строку в набор байт любой известной ей кодировки. Для этого есть специальные методы у класса String(!). Также в Java есть специальный класс Charset, который описывает конкретную кодировку.
1) Как получить список всех кодировок, с которыми Java может работать?
Для этого есть специальный статический метод availableCharsets. Этот метод возвращает набор пар (имя кодировки, объект описывающий кодировку)
SortedMap<String,Charset> charsets = Charset.availableCharsets();
У каждой кодировки есть уникальное имя, вот некоторые из них: UTF-8, UTF-16, Windows-1251, KOI8-R,…
2) Как получить текущую активную кодировку (Unicode)?
Для этого есть специальный метод defaultCharset
Charset currentCharset = Charset.defaultCharset();
3) Как преобразовать строку в определенную кодировку?
В Java на основе строки можно создать массив байт в любой известной Java кодировке:
Метод | Пример |
---|---|
|
|
|
|
|
|
4) А как преобразовать набор байт, которые я прочитал из файла в строку, если я знаю в какой кодировке они были в файле?
Тут все еще проще – у класса String есть специальный конструктор:
Метод | Пример |
---|---|
|
|
|
|
|
|
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);
— Я так и думал. Спасибо за интересную лекцию, Риша.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ