Кодировка UTF-8 выводит неверную кодировку в Windows Hotspot JVM 1.8.0_201 - PullRequest
0 голосов
/ 17 марта 2019

Извините, если это глупый вопрос, я могу упустить что-то простое здесь.

Я просто пытаюсь кодировать строку, используя UTF-8. Следуя рекомендациям, я не предполагаю, что кодировкой по умолчанию является UTF-8, и поэтому я использую:

"Ñ".getBytes(Charset.forName("UTF-8"))

В соответствии с официальной спецификацией Unicode это должно выглядеть так: 0xc391

Однако вместо этого я получаю: 0xc383e28098.

Я не понимаю этого. Это происходит независимо от того, установил я -Dfile.encoding=UTF-8 или нет.

Как ни странно, когда я не указываю кодировку (или использую Charset.defaultCharset()), используется кодировка windows-1252, и выходной код корректно кодируется UTF-8!

Более того, когда я запускаю код через IntelliJ, а не из командной строки, кодировка UTF-8 действительно работает, как и ожидалось. IntelliJ добавляет множество несвязанных библиотек в путь к классам, поэтому я думаю, что одна из них отвечает за исправление, но я хочу, чтобы она работала в производстве.

Мой java -version:

java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) Client VM (build 25.201-b09, mixed mode

1 Ответ

2 голосов
/ 17 марта 2019

В вашем коде нет ничего плохого.Проблема в том, как компилятор обрабатывает ваш исходный код.

Когда вы пишете "Ñ" в своем коде и сохраняете файл, какие байты фактически записываются в исходный файл?

Похоже, высохранил исходный файл как файл UTF-8 (который обычно является хорошим выбором).Это означает, что "Ñ" было записано в файл в виде байтов UTF-8 0xC3 0x91.

Если вы должны были скомпилировать его в любой операционной системе, кроме Windows, где системная кодировка по умолчанию - UTF-8,будет собираться и работать точно так, как вы ожидаете.

Но при сборке в Windows, где системная кодировка по умолчанию - windows-1252, эти два байта в исходном файле обрабатываются по-разному.Компилятор интерпретирует эти два байта, используя windows-1252.Независимо от того, как код выглядит в вашем редакторе, компилятор видит 0xC3 0x91 и обрабатывает каждый байт как windows-1252 символ .В windows-1252 эти байты представляют собой:

Таким образом, компилятор компилирует вашу строковую константу как `" Ã '".

Весь этот перевод выполнялся только во время компиляции,В скомпилированном файле .class все строковые константы представлены одинаково;любая информация о том, как был закодирован источник, теряется.Во время выполнения Java знает только, что вы (очевидно) скомпилировали вашу строку как "Ñ".

Во время выполнения, когда вы декодируете эту двухсимвольную строку с использованием UTF-8, вы получаете байтовые последовательности UTF-8для этих двух символов:

  • Ã → 0xc3 0x83
  • → 0xe2 0x80 0x98

Решение, как вы уже догадались,сообщить компилятору, что ваши исходные файлы находятся в UTF-8, поэтому он будет интерпретировать байты 0xc3 0x91 как Ñ.

...