Должен ли я всегда обернуть InputStream как BufferedInputStream? - PullRequest
39 голосов
/ 03 июня 2010

Имеет ли смысл всегда оборачивать InputStream как BufferedInputStream, когда я знаю, является ли данный InputStream чем-то отличным от буферизованного? Например:

InputStream is = API.getFromSomewhere()
if(!(is instanceof BufferedInputStream))
  return new BufferedInputStream(is);
return is;

Ответы [ 4 ]

33 голосов
/ 03 июня 2010

Имеет ли смысл всегда оборачивать InputStream как BufferedInputStream, когда я знаю, является ли данный InputStream чем-то отличным от буферизованного?

номер

Имеет смысл, если вы, скорее всего, будете выполнять много небольших операций чтения (по одному или нескольким байтам за раз) или если вы хотите использовать некоторые из функций более высокого уровня, предлагаемых буферизованными API; например метод BufferedReader.readLine().

Однако, если вы собираетесь выполнять чтение больших блоков только с помощью методов read(byte[]) и / или read(byte[], int, int), перенос InputStream в BufferedInputStream не поможет.

(В ответ на комментарий @Peter Tillman'а к своему собственному ответу, варианты использования чтения блоков определенно представляют более 0,1% случаев использования классов InputStream !! Однако он прав в том смысле, что обычно безвредно для использования буферизованного API, когда вам это не нужно.)

6 голосов
/ 03 июня 2010

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

Если потребителю это нужно, лучше обернуть его там.

2 голосов
/ 03 июня 2010

Возможно, вам не всегда нужна буферизация, поэтому ответом будет «Нет», в некоторых случаях это просто накладные расходы.

Есть еще одна причина, по которой это «Нет», и она может быть более серьезной. BufferedInputStream (или BufferedReader) может вызвать непредсказуемые сбои при использовании с сетевым сокетом, когда вы также включили тайм-аут на сокете. Тайм-аут может возникнуть при чтении пакета. Вы больше не сможете получить доступ к данным, которые были переданы в эту точку - даже если вы знали, что было некоторое ненулевое число байтов (см. java.net.SocketTimeoutException, который является подклассом java.io.InterruptedIOException, поэтому имеет переменную bytesTransferred имеется).

Если вам интересно, как может произойти тайм-аут сокета во время чтения, просто подумайте о вызове метода read(bytes[]), и исходный пакет, содержащий сообщение, в итоге был разделен, но один из частичных пакетов задерживается по истечении времени ожидания ( оставшаяся часть тайм-аута). Это может происходить чаще, когда снова заключено в нечто, реализующее java.io.DataInput (любое из чтений для нескольких байтовых значений, например readLong() или readFully() или метод BufferedReader.readLine().

Обратите внимание, что java.io.DataInputStream также является плохим кандидатом для потоков сокетов, которые имеют тайм-аут, так как он также плохо работает с исключениями тайм-аута.

0 голосов
/ 03 июня 2010

Это также зависит от того, как вы собираетесь читать из InputStream. Если вы собираетесь читать символ / байт за раз (то есть read ()), то BufferedInputStream уменьшит ваши накладные расходы, выполняя массовое чтение от вашего имени. Если вы собираетесь читать его в массив из 4k или 8k byte / char блок за раз, тогда BuffredInputStream, вероятно, не принесет вам пользы.

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