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

Разве размер символов в Java не равен 2 байтам?

Я использовал RandomAccessFile для чтения a byte из текстового файла.

public static void readFile(RandomAccessFile fr) {
    byte[] cbuff = new byte[1];
    fr.read(cbuff,0,1);
    System.out.println(new String(cbuff));
}

Почему я вижу один полный символ, читаемый этим?

4b9b3361

Ответ 1

A char представляет символ в Java (*). Это 2 байта большой (по крайней мере, то, что предлагает допустимый диапазон значений).

Это не обязательно означает, что каждое представление символа имеет длину 2 байта. На самом деле многие кодировки сохраняют только 1 байт для каждого символа (или используют 1 байт для наиболее распространенных символов).

Когда вы вызываете конструктор String(byte[]), вы запрашиваете Java для преобразования byte[] в String с использованием кодировки по умолчанию платформы. Поскольку стандартная кодировка платформы обычно представляет собой 1-байтовое кодирование, такое как ISO-8859-1 или кодирование переменной длины, такое как UTF-8, оно может легко преобразовать этот 1 байт в один символ.

Если вы запустите этот код на платформе, использующей UTF-16 (или UTF-32 или UCS-2 или UCS-4 или...) в качестве кодировки по умолчанию для платформы, то вы не получите действительный результат (вы 'вместо a String, содержащего символ замены Unicode).

Это одна из причин, почему вы не должны зависеть от кодировки по умолчанию платформы: при преобразовании между byte[] и char[]/String или между InputStream и Reader или между OutputStream и Writer, вы должны всегда указать, какую кодировку вы хотите использовать. Если вы этого не сделаете, ваш код будет зависящим от платформы.

(*), что не совсем верно: a char представляет собой кодовую точку UTF-16. Либо один, либо два кодовых UTF-16 представляют собой код Unicode. Кодовое обозначение Unicode обычно представляет собой символ, но иногда несколько кодов Unicode используются для создания одного символа. Но приведенное выше приближение достаточно близко, чтобы обсудить эту тему.

Ответ 2

Java хранит все "chars" внутренне как два байта. Однако, когда они становятся строками и т.д., Количество байтов будет зависеть от вашей кодировки.

Некоторые символы (ASCII) являются одиночными байтами, но многие другие являются многобайтовыми.

Java поддерживает Unicode, поэтому в соответствии с:

Документы Java Character

Максимальное поддерживаемое значение - "\ uFFFF" (hex FFFF, dec 65535) или 11111111 11111111 двоичный (два байта).

Ответ 3

Конструктор String(byte[] bytes) берет байты из буфера и кодирует их в символы.

Он использует кодировку платформы по умолчанию для кодирования байтов для символов. Если вы знаете, ваш файл содержит текст, который закодирован в другой кодировке, вы можете использовать String(byte[] bytes, String charsetName) для использования правильной кодировки (от байтов до символов).

Ответ 4

В текстовом файле ASCII каждый символ всего один байт

Ответ 5

Похоже, ваш файл содержит символы ASCII, которые закодированы только в 1 байт. Если текстовый файл содержит не-ASCII-символ, например. 2-байтовый UTF-8, тогда вы получите только первый байт, а не весь символ.

Ответ 6

Здесь есть несколько отличных ответов, но я хотел бы указать, что jvm может хранить значение char в любом пространстве размерa >= 2 байта.

На многих архитектурах существует штраф за выполнение нерационального доступа к памяти, поэтому char может быть легко дополнен до 4 байтов. Волатильный char может быть даже добавлен к размеру строки кэша CPU для предотвращения ложного обмена. https://en.wikipedia.org/wiki/False_sharing

Это может быть неинтуитивно понятным для новых программистов Java, что массив символов или строка НЕ ​​являются просто несколькими символами. Вы должны учиться и думать о строках и массивах четко из "нескольких персонажей".

Я также хочу указать, что символы Java часто используются неправильно. Люди не понимают, что они пишут код, который не будет правильно обрабатывать кодовые страницы более 16 бит.

Ответ 7

Java выделяет 2 из 2 байтов для символа, как следует из UTF-16. Он занимает минимум 2 байта при сохранении символа и максимум 4 байта. Для символа нет 1 байта или 3 байта памяти.