Подтвердить что ты не робот

Как Java соответствует 3-байтовому символу Unicode в тип char?

Итак, "char" в Java - 2 байта. (Можно проверить здесь.)

У меня есть этот пример кода:

public class FooBar {
    public static void main(String[] args) {
        String foo = "€";
        System.out.println(foo.getBytes().length);
        final char[] chars = foo.toCharArray();
        System.out.println(chars[0]);
    }
}

И вывод выглядит следующим образом:

3
€

Мой вопрос в том, как Java соответствовала 3-байтовому символу в тип данных char? BTW, я запускаю приложение с параметром: -Dfile.encoding = UTF-8

Также, если я немного отредактирую код и добавлю следующие утверждения:

File baz = new File("baz.txt");
final DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(baz));
dataOutputStream.writeChar(chars[0]);
dataOutputStream.flush();
dataOutputStream.close();

окончательный файл "baz.txt" будет всего 2 байта, и он не будет показывать правильный символ, даже если я рассматриваю его как файл UTF-8.

Изменить 2: Если я открою файл "baz.txt" с кодировкой UTF-16 BE, я увижу, что символ "очень хорошо" в текстовом редакторе, что имеет смысл, я думаю.

4b9b3361

Ответ 1

String.getBytes() возвращает байты, используя кодировку символов по умолчанию платформы, которая не обязательно соответствует внутреннему представлению.

Java, использующая 2 байта в ram для каждого char, когда символы "сериализуются" с использованием UTF-8, они могут генерировать один, два или три байта в результирующем массиве байтов, как работает кодировка UTF-8.

В вашем примере кода используется UTF-8. Строки Java кодируются в памяти с использованием UTF-16. Кодовые страницы Unicode, которые не помещаются в один 16-разрядный char, будут закодированы с использованием пары 2- char, известной как суррогатная пара.

Если вы не передадите значение параметра в String.getBytes(), он возвращает массив байтов, который содержит содержимое String, закодированное с использованием базовой кодировки по умолчанию для ОС. Если вы хотите обеспечить кодированный UTF-8 массив, тогда вам нужно использовать getBytes ( "UTF-8" ).

Вызов String.charAt() возвращает исходный UTF-16-кодированный char только из памяти в строковой памяти.

Проверьте эту ссылку: java utf8 encoding - char, типы строк

Ответ 2

Java использует UTF-16 (16 бит) для представления в памяти.

Этот символ евро вписывается в это, хотя ему нужно три байта в UTF-8.