Arhn - архитектура программирования

Когда я назначаю char (из буквального или иного), какая внутренняя кодировка Java здесь означает UTF16? В какой кодировке он хранится в char?

//non-utf source file encoding
char ch = 'ё'; // some number within 0..65535 is stored in char. 
System.out.println(ch); // the same number output to 

"внутренняя кодировка Java — UTF16". Где он осмысленно играет в этом?

Кроме того, я могу идеально поместить в char один кодовый модуль utf16 из суррогатного диапазона (скажем, '���'), что сделает этот char абсолютно недействительным Unicode. И давайте останемся в BMP, чтобы не думать, что у нас может быть 2 символа (codeunit) для дополнительного символа (думать, что таким образом звучит для меня, что «char внутренне использует utf16» — полная ерунда). Но может быть, "char внутренне использует utf16" имеет смысл в BMP?

Я мог бы понять это, если бы было так: мой файл исходного кода находится в кодировке Windows-1251, литерал char преобразуется в число в соответствии с кодировкой Windows-1251 (что на самом деле происходит), затем это число автоматически преобразуется в другое число (из Windows -1251 номер в номер utf-16) - чего НЕ происходит (я прав?! это я мог понять как «внутренне использует UTF-16»). И затем этот сохраненный номер записывается (на самом деле он записывается как заданный, как из win-1251, никакого моего «воображаемого преобразования из внутренней utf16 в кодировку вывода\консоли» не происходит), консоль показывает, что это преобразование из числа в глиф с помощью консоли кодирование (что происходит на самом деле)

Таким образом, эта «внутренняя кодировка UTF16» НИКОГДА НЕ ИСПОЛЬЗУЕТСЯ ??? char просто хранит любое число (в [0..65535]), и, кроме определенного диапазона и «без знака», НЕ ОТЛИЧАЕТСЯ ОТ int (конечно, в рамках моего примера)???

P.S. Экспериментально код выше с кодировкой UTF-8 исходного файла и выводов консоли

й
1081

с кодировкой исходного файла win-1251 и UTF-8 в выводе консоли

�
65533

Тот же вывод, если мы используем String вместо char...

String s = "й";
System.out.println(s);

В API все методы, принимающие char в качестве аргумента, обычно никогда не принимают в качестве аргумента кодировку. Но методы, принимающие byte[] в качестве аргумента, часто принимают кодировку в качестве другого аргумента. Подразумевается, что с char нам не нужна кодировка (это означает, что мы точно знаем эту кодировку). Но **как мы узнаем, в какой кодировке что-то было помещено в char???

Если char — это просто хранилище для числа, нам нужно понять, из какой кодировки исходно получено это число?**
Итак, char vs byte — это всего лишь то, что char имеет два байта чего-то с кодировкой UNKNOWN (вместо одного байта НЕИЗВЕСТНАЯ кодировка байта). Учитывая некоторую инициализированную переменную char, мы не знаем, какую кодировку использовать для ее правильного отображения (чтобы выбрать правильную кодировку консоли для вывода), мы не можем сказать, какая была кодировка исходного файла, где он был инициализирован литералом char (не считая случаев совместимости различных кодировок и utf).

Я прав, или я большой идиот? Извините за вопрос в последнем случае :)))

Исследование SO не дает прямого ответа на мой вопрос:


  • Учитывая некоторую инициализированную переменную char, мы не знаем, какую кодировку использовать для ее правильного отображения (чтобы выбрать правильную кодировку консоли для вывода). необходимо знать кодировку символов этой консоли для правильного отображения символа (если это вообще возможно). Символ однозначно в UTF-16. 13.06.2017
  • Означает ли это, что in char ch = 'й'; литерал 'й' всегда преобразуется в utf16 из любого исходного файла кодировки? 13.06.2017
  • @LrnBoy да, точно. 13.06.2017

Ответы:


1

В большинстве случаев лучше всего думать о char как об определенном символе (независимо от какой-либо кодировки), например. символ 'A', а не как 16-битное значение в какой-то кодировке. Только когда вы конвертируете между char или String и последовательностью байтов, кодировка играет роль.

Тот факт, что char внутренне кодируется как UTF-16, важен только в том случае, если вам приходится иметь дело с его числовым значением.

Суррогатные пары имеют смысл только в последовательности символов. Один char не может содержать значение символа вне BMP. Здесь ломается абстракция персонажа.

13.06.2017

2

Юникод — это система представления текстовых данных в виде кодовых точек. Обычно это символы, но не всегда. Кодовая точка Unicode всегда представлена ​​в некоторой кодировке. Наиболее распространенными являются UTF-8, UTF-16 и UTF-32, где число указывает количество битов в кодовой единице. (Например, UTF-8 кодируется как 8-битные байты, а UTF-16 кодируется как 16-битные слова.)

В то время как первая версия Unicode допускала кодовые точки только в диапазоне 0hex ... FFFFhex, в Unicode 2.0 они изменили диапазон на 0hex< /sub> в 10FFFFhex.

Итак, очевидно, что Java (16-битная) char уже недостаточно велика для представления всех кодовых точек Unicode.

Это возвращает нас к UTF-16. Java char может представлять кодовые точки Unicode, которые меньше или равны FFFFhex. Для больших кодовых точек представление UTF-16 состоит из 2 16-битных значений; так называемая суррогатная пара. И это поместится в 2 Java chars. Таким образом, стандартное представление Java String представляет собой последовательность значений char, которые составляют UTF-16-представление кодовых точек Unicode.

Если мы работаем с большинством современных языков (включая CJK с упрощенными символами), все интересующие кодовые точки Unicode находятся в нулевой кодовой плоскости (от 0hex до FFFFhex) . Если вы можете сделать такое предположение, то можно рассматривать char как кодовую точку Unicode. Однако все чаще мы видим кодовые точки на более высоких планах. Распространенным случаем являются кодовые точки для эмодзи.)

Если вы посмотрите на javadoc для класса String, вы увидите кучу строк методов codePointAt, codePointCount и так далее. Это позволяет вам обрабатывать текстовые данные правильно... то есть иметь дело с суррогатными парами.


Итак, как это связано с UTF-8, windows-1251 и так далее?

Ну, это 8-битные кодировки символов, которые используются на уровне ОС в текстовых файлах и так далее. Когда вы читаете файл с помощью Java Reader, ваш текст фактически транскодируется из UTF-8 (или Windows-1251) в UTF-16. Когда вы выписываете символы (используя Writer), вы перекодируете в другом направлении.

Это не всегда работает.

  • Многие кодировки символов, такие как windows-1251, не могут отображать весь диапазон кодовых точек Unicode. Таким образом, если вы попытаетесь написать (скажем) символ CJK через Writer, сконфигурированный для Windows-1251, вместо этого вы получите ? символов.

  • Если вы читаете закодированный файл, используя неправильную кодировку символов (например, если вы пытаетесь прочитать файл UTF-8 как windows-1251 или наоборот), то транскодирование может дать мусор. Это явление настолько распространено, что у него даже есть название: моджибаке).


Ты спросил:

Означает ли это, что in char ch = 'й'; литерал 'й' всегда преобразуется в utf16 из любого исходного файла кодировки?

Теперь мы (предположительно) говорим об исходном коде Java. Ответ заключается в том, что это зависит. По сути, вам нужно убедиться, что компилятор Java использует правильную кодировку для чтения исходного файла. Обычно это указывается с помощью параметра командной строки -encoding. (Если вы не укажете -encoding, то будет использоваться «преобразователь платформы по умолчанию»; см. ручную запись javac.)

Предполагая, что вы скомпилировали исходный код с правильной кодировкой (т. е. совпадающей с фактическим представлением в исходном файле), компилятор Java выдаст код, содержащий правильное представление UTF-16 любых строковых литералов.

Однако обратите внимание, что это независимо от кодировки символов, используемой вашим приложением для чтения и записи файлов во время выполнения. Эта кодировка определяется тем, что выбирает ваше приложение, или кодировкой платформы выполнения по умолчанию.

13.06.2017
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..


© 2024 arhn.ru, Arhn - архитектура программирования