Заблуждения о потоке Java ... некоторые уточнения? - PullRequest
3 голосов
/ 11 августа 2011

Я понимаю, что потоки байтов имеют дело с байтами, а потоки символов имеют дело с символами ... если я использую поток байтов для чтения в символах, может ли это ограничить меня типами символов, которые я мог бы прочитать?Например, байты считываются как 8-битные байты, а символы читаются как 16-битные символы ... означает ли это, что большее количество символов может быть представлено с использованием символьных потоков, а не байтовых потоков?сбит с толку то, как поток байтов записывает в файл для чтения.Если бы я получал байты из сетевого сокета, я бы обернул их в InputStreamReader для записи, таким образом я бы получил логику преобразования символов, которую обеспечивает поток символов.Если я читаю из файла FileInputStream и записываю FileOutputStream, почему этот файл читается, когда я открываю его в текстовом редакторе?Как FileOutputStream обрабатывает байты?

Ответы [ 5 ]

3 голосов
/ 11 августа 2011

Ключевой концепцией здесь является кодировка символов : каждый читаемый человеком символ каким-то образом кодируется в один или несколько байтов. Есть много кодировок символов. Самые популярные из них:

  • ASCII (7 бит, оставшийся бит не используется), который обрабатывает один символ как один байт
  • UTF-8: наиболее распространенные символы представлены в виде одного байта, менее распространены как 2 или даже больше

Эти кодировки доступны для чтения даже при открытии файла в шестнадцатеричном редакторе. Однако существует много кодировок символов, которые не имеют этой функции, а именно UTF-16 и UTF-32.

Теперь вернемся к вашему вопросу: InputStream дает вам только поток байтов. Если ваши байты представляют собой символы, закодированные с помощью ASCII или UTF-8, большую часть времени у вас все в порядке. Но если эти байты представляют что-то более сложное, например, UTF-16, вам абсолютно необходим Reader. Конечно, читатель должен знать, какую кодировку символов обеспечивает базовый InputStream. Это часто проблема, которую делают новички - Reader, не инициализированный явным образом с помощью кодировки символов, часто возвращается к системному значению по умолчанию.

Другой способ (с писателями) аналогичен. Если вы просто преобразуете свои char s в byte s, большую часть времени у вас все будет хорошо. Но если ваши символы содержат менее популярные национальные буквы, ваш вывод будет искажен / усечен. Таким образом, вы создаете Writer, который преобразует каждый данный символ в серию из одного или нескольких байтов. Еще раз вы обязаны предоставить кодировку символов.

Важные правила:

  • всегда используйте InputStream при работе с двоичными данными (мультимедиа, файлы ZIP и PDF и т. Д.)
  • всегда использовать Reader при чтении текста (txt, HTML, XML ...)
  • всегда знать и указывать кодировку символов при чтении символа из потока байтов, всегда сознательно выбирать кодировку символов, которую вы используете для записи данных.
2 голосов
/ 11 августа 2011

A char - это 16-битная строка, представляющая символ Unicode.

A byte - это 8-битная строка, представляющая число дополнения до 2.

Важная вещь здесьв том, что они оба являются битовыми строками.Технически говоря, char - это просто 2 byte с.Не более, не менее, за исключением незначительной семантики того, как Java обращается с ними.Что касается компьютера (или Input/OutputStream s), единственное различие заключается в количестве бит, которые они содержат.

1 голос
/ 11 августа 2011

Я думаю, вам нужно понять связь между байтом и символом, чтобы получить ваше разъяснение.

Принятый ответ на этот вопрос совершенно ясен ИМХО: Почему байт в JavaВвод / вывод может представлять символ?

Я бы также проверил поток байтов и поток символов

А если вы не хотите, чтобы Джоэл ловилты и заставляешь чистить лук в течение 6 месяцев на подводной лодке, просто читай http://www.joelonsoftware.com/articles/Unicode.html

0 голосов
/ 11 августа 2011

Чтобы ответить на ваши вопросы:

Я понимаю, что потоки байтов имеют дело с байтами, а потоки символов имеют дело с символами ... если я использую поток байтов для чтения символов, это может ограничить менякакие символы я могу читать?

Символы не являются байтами.Символ сохраняется в одном или нескольких байтах в соответствии с выбранной схемой кодирования.Схема кодирования снимает / расширяет ограничение на количество видов символов, которые вы можете прочитать.

Например, байты считываются как 8-битные байты, символы читаются как 16-битные символы ... делает этоозначает, что больше символов может быть представлено с использованием символьных потоков, а не байтовых потоков?

В некотором смысле, да.

Последнее, что меня смущает, - это как поток байтовзаписывает в файл для чтения.Если бы я получал байты из сетевого сокета, я бы обернул их в InputStreamReader для записи, таким образом я бы получил логику преобразования символов, которую обеспечивает поток символов.Если я читаю из файла с помощью FileInputStream и записываю с помощью FileOutputStream, почему этот файл читается, когда я открываю его в текстовом редакторе?Как FileOutputStream обрабатывает байты?

Для байтов / данных, соответствующих символам, вы должны использовать OutputStreamWriter для записи в файл и сделать его читаемым с помощью текстового редактора.Вы можете указать кодировку при создании, и поток будет выполнять кодирование ваших текстовых данных.

0 голосов
/ 11 августа 2011

Все потоки ввода-вывода в Java - это только байтовые потоки внизу. Преобразование байтов в символы (и наоборот) выполняется с использованием кодирования. Но под всем этим они все байты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...