Разве размер символов в 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));
}
Почему я вижу один полный символ, читаемый этим?
Ответы
Ответ 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 байта памяти.