Кодировки в Java

Кодировки в Java

Aleksandr Kuzmichev

Где мы можем споткнуться о кодировки в Java? Давай разберемся.

Простейший процесс разработки Java-приложения состоит трех из шагов:

1. создать в блокноте файл с java кодом

2. скомпилировать этот файл с помощью команды javac

3. запустить этого файла с помощью команды java (отправляем скомпилированный класс JVM-ке)


Сценарий прост - как фисташку открыть. Но он насквозь пронизан работой с кодировками. Кодировка - это таблица где каждому символу соответствует какое-то число. В памяти символы хранятся как числа - числа из таблицы кодировки. Пример ASCII кодировки для чуть большей наглядности:

Кодировка ASCII - каждому символу соответствует свое число.

Кодировки бывают разными - как правило все включают в себя буквы английского алфавита и общепринятые символы типа тех что вы видите на числовом ряде клавиатуры. А вот символы других языков могут присутствовать, а могут не присутствовать в определенной кодировке. А могут присутствовать, но с другим номером. Т.е. если в памяти лежит число 165 - разной кодировкой он прочитается по разному:

UTF-8: ¥

CP1251: Х (русская)

KOI8-R: И

Именно во время таких несоответствий (файл закодирован одной кодировкой, а читаем мы его другой) - рождаются кракозябры, типа такого:

ÇÒÁÍÏÔÁ ÏÔ ëÕÚØÍÉÞÁ

ÓàÐÜÞâÐ Þâ ºã×ìÜØçÐ

╨│╤А╨░╨╝╨╛╤В╨░ ╨╛╤В ╨Ъ╤Г╨╖╤М╨╝╨╕╤З╨░


Вернемся к нашему сценарию разработки Java-приложения в Windows системе и разберем четыре места встречи с кодировками, каждое представлено этапом на картинке:

1. file encoding

Для начала - созданный App.java файл сохраняется в какой-то конкретной кодировке. Чаще всего - это UTF-8, но могут быть и другие варианты. Следите за тем в какой кодировке сохраняете свой файл, на следующих этапах это будет важно.

2. compilator encoding

Далее - мы хотим что бы компилятор обработал наш файл - для этого компилятору нужно знать с помощью какой кодировки прочитать наш файл. По умолчанию javac будет использовать дефолтную кодировку операционной системы. Хорошо если это например UTF-8. И плохо если это что-то другое, например windows-1251. Символы в ней хранятся уже в другом порядке, и тут начинается проблема с кириллицей - поэтому мы и используем флаг

javac -encoding UTF-8 App.java 

чтобы подсказать компилятору как правильно прочитать наш App.java файл.

3. JVM encoding

Хочется сказать что теперь мы подстелили соломку - но есть еще два места где все может пойти не так.

Во-первых, когда мы вызовем -

java App

- JVM тоже попробует использовать дефолтную кодировку при операциях ввода\вывода, в т.ч. для печати данных в консоль. И тут мы тоже можем напороться на то, что App.class был скомпилирован в UTF-8, а данные из него мы будем отправлять на печать снова в windows-1251. Чтобы этого не произошло - используем флаг

java -Dfile.encoding=UTF-8 EncodingTest

4. console encoding

Ура? Нет! Консоль с которой вы работаете (windows cmd / powershell / bash) и куда java будет сыпать строки из System.out.println() - тоже имеет кодировку! Например в windows кодировку консоли можно узнать через команду 'chcp', а если вы увидели там что-то незнакомое - можете поменять ее на кодировку 65001 (это аналог UTF-8 в Windows.):

chcp 65001


И только после всех этих шагов и нюансов нас ожидает счастливый конец. Хотя для старых версий powershell потребуется особая щепотка магии, но об этом как-нибудь в другой раз.

Report Page