JavaRush /Курсы /Java Multithreading /Character, кодировки

Character, кодировки

Java Multithreading
2 уровень , 10 лекция
Открыта

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

Сейчас будет еще одна интересная тема – кодировки.

Возможно, ты где-то уже слышал, что у каждого символа есть код (число). Именно поэтому тип 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 может работать?

Для этого есть специальный статический метод 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 кодировке:

Метод Пример
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(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) А как преобразовать набор байт из одной кодировки в другую?

Есть много способов. Вот тебе один из самых простых:

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

— Я так и думал. Спасибо за интересную лекцию, Риша.

Комментарии (83)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Никита Уровень 37
3 октября 2025
было бы полезно оставить пару слов про утилитарный класс java.nio.charset.StandardCharsets
No Name Уровень 36
23 ноября 2024
+ лекция в копилке
Максим Li Уровень 40
19 мая 2024
19.05.2024
Ислам Уровень 33
17 марта 2024
Nice
Dmitry Shaburov Уровень 33
7 марта 2024
07.03.2024
Denis Odesskiy Уровень 47
18 ноября 2023
Приходит программист к окулисту. Тот его усаживает напротив таблицы, берёт указку и говорит: -Читайте! -"БНОПНЯ" ... Доктор, у вас что-то не то с кодировкой!
arsvasimov Уровень 51
29 мая 2025
😂
Denys Sukhoivan Уровень 30 Expert
10 августа 2023
Ничего не понятно, но очень интересно )))
26 сентября 2022
просто прочитал вообще не вникая. Не сумели заинтересовать т.к. не написано где это будет применяться и на сколько оно важно. Если оно пригодится раз в 10 лет то можно и нагуглить потом как определить кодировку или с одной в другую перегнать.
Dmitry Уровень 26
25 января 2023
Как будто ты ни разу не сталкивался с тем, что вместо текста видишь какие-то закорючки, особенно если используешь кириллицу в американском ПО.
Lafaed Уровень 36
3 марта 2023
Не то чтоб не заинтересовали, скорее просто не зашло как-то.
Тимофей Уровень 51
17 июня 2023
чувак я на работе с этой задачей жестко завис, на несколько дней. Документы могут быть загружены в windows-1251, а после обработки парсером они станут кракозябрами, а пользователям оно не к чему. Ты не представляешь какое это болото, я написал все методы, написал тесты, а потом оказалось когда я мавеном прогнал тесты - что мавен windows 1251 использует, а не UTF-8 и теперь нужно уже это решать. Какая же боль эти кодировки
Дмитрий Уровень 46
22 июля 2022
Огонь hкодировки
Anonymous #3062817 Уровень 47
10 июля 2022
Я знаю что ты только притворяешься - Амиго!