Разница между InputStream и InputStreamReader при чтении многобайтовых символов
Разница между InputStream
и InputStreamReader
заключается в том, что InputStream
читается как byte
, а InputStreamReader
читается как char
. Например, если текст в файле abc
, то оба они работают нормально. Но если текст a你们
, который состоит из a
и двух китайских символов, то InputStream
не работает.
Итак, мы должны использовать InputStreamReader
, но мой вопрос:
Как InputStreamReader
распознать символы?
a
- один байт, но китайский символ - два байта. Прочитал ли он a
как один байт и распознал другие символы как два байта или для каждого символа в этом тексте, читает ли он InputStreamReader
как два байта?
Ответы
Ответ 1
An InputStream
считывает необработанные октетные (8-битные) данные. В Java тип byte
эквивалентен типу char
в C. В C этот тип может использоваться для представления символьных данных или двоичных данных. В Java тип char
имеет большее сходство с типом C wchar_t
.
An InputStreamReader
затем преобразует данные из некоторой кодировки в UTF-16. Если "a 你们" закодирован как UTF-8 на диске, это будет последовательность байтов 61 E4 BD A0 E4 BB AC
. Когда вы передаете InputStream
в InputStreamReader
с кодировкой UTF-8, она будет считана как последовательность char 0061 4F60 4EEC
.
API кодировки символов в Java содержит алгоритмы для выполнения этого преобразования. Вы можете найти список кодировок, поддерживаемых Oracle JRE здесь. ICU project - хорошее место для начала, если вы хотите понять внутренности того, как это работает на практике.
Как указывает Александр Погребняк , вы почти всегда должны предоставлять кодировку явно. byte
-to- char
, которые не указывают кодировку, полагаются на JRE default, который зависит от операционных систем и пользователя настройки.
Ответ 2
Вам нужно дать подсказку читателю, указав набор символов, в котором записано двоичное файл. Например:
Reader reader =
new InputStreamReader(
new FileInputStream( "/path/to/file" ),
"UTF-8" // most likely that the encoding of the file
)
Без подсказки он будет использовать кодировку по умолчанию для платформы, которая во многих случаях не является тем, что вы хотите.
Эта ссылка имеет хорошее объяснение кодировок: http://www.joelonsoftware.com/articles/Unicode.html