Должен ли я всегда включать InputStream как BufferedInputStream?

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

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

Ответ 1

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

Нет.

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 4

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