Разница между InputStream и InputStreamReader при чтении многобайтовых символов - PullRequest
28 голосов
/ 23 апреля 2011

Разница между InputStream и InputStreamReader заключается в том, что InputStream читается как byte, а InputStreamReader читается как char. Например, если текст в файле abc, то оба они работают нормально. Но если текст a你们, который состоит из a и двух китайских иероглифов, то InputStream не работает.

Итак, мы должны использовать InputStreamReader, но мой вопрос:

Как InputStreamReader распознает символы?

a - один байт, но китайский символ - два байта. Читает ли он a как один байт и распознает другие символы как два байта, или для каждого символа в этом тексте InputStreamReader читает его как два байта?

Ответы [ 2 ]

27 голосов
/ 23 апреля 2011

InputStream читает необработанные октетные (8-битные) данные. В Java тип byte эквивалентен типу char в C. В C этот тип может использоваться для представления символьных данных или двоичных данных. В Java тип char имеет большее сходство с типом C wchar_t.

InputStreamReader затем преобразует данные из некоторой кодировки в UTF-16. Если «a a» закодировано как UTF-8 на диске, это будет последовательность байтов 61 E4 BD A0 E4 BB AC. Когда вы передаете InputStream в InputStreamReader с кодировкой UTF-8, он будет читаться как последовательность символов 0061 4F60 4EEC.

API кодировки символов в Java содержит алгоритмы для выполнения этого преобразования. Вы можете найти список поддерживаемых Oracle JRE кодировок здесь . Проект ICU - хорошее место для начала, если вы хотите понять, как это работает на практике.

Как отмечает Александр Погребняк , вы почти всегда должны предоставлять кодировку явно. Методы byte -to- char, в которых не указана кодировка, основаны на JRE по умолчанию , которое зависит от операционной системы и пользовательских настроек.

10 голосов
/ 23 апреля 2011

Вы должны дать читателю подсказку, предоставив набор символов, в котором записан ваш двоичный файл. E.g

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

...