web-dev-qa-db-ja.com

InputStreamを常にBufferedInputStreamとしてラップする必要がありますか?

指定されたInputStreamがバッファリングされたもの以外であるかどうかを知っているとき、常にInputStreamをBufferedInputStreamとしてラップすることは意味がありますか?例:

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

指定されたInputStreamがバッファリングされたもの以外であるかどうかがわかっている場合、always InputStreamをBufferedInputStreamとしてラップすることは意味がありますか?

番号。

大量の小さな読み取り(一度に1バイトまたは数バイト)を実行する可能性がある場合、またはバッファーAPIによって提供されるより高いレベルの機能の一部を使用する場合は、理にかなっています。たとえば、BufferedReader.readLine()メソッド。

ただし、read(byte[])および/またはread(byte[], int, int)メソッドを使用して大きなブロックの読み取りのみを実行する場合は、InputStreamBufferedInputStreamでラップすると助けません。

(自分の回答に対する@Peter Tillmanのコメントに応じて、ブロック読み取りのユースケースはInputStreamクラスの使用の0.1%以上を確実に表します!!しかし、彼は通常そうであるという意味で正しいです- 無害必要のないときにバッファAPIを使用します。)

34
Stephen C

私はそれをしません、可能な限り最高の抽象化レベルのままにしておきます。 BufferedStreamのマークおよびリセット機能を使用しない場合、なぜわざわざそれをラップするのでしょうか。

消費者がそれを必要とするなら、それをそこに包む方が良いです。

6
Peter Tillemans

常にバッファリングが必要なわけではないので、そのための答えは「いいえ」になります。

それが「いいえ」である別の理由があり、それはより深刻になる可能性があります。 BufferedInputStream(またはBufferedReader)をネットワークソケットで使用すると、ソケットのタイムアウトも有効にした場合、予期しないエラーが発生する可能性があります。パケットの読み取り中にタイムアウトが発生する可能性があります。その時点に転送されたデータにアクセスできなくなります-ゼロ以外のバイト数があることがわかっていても(_Java.net.SocketTimeoutException_のサブクラスである_Java.io.InterruptedIOException_を参照)、 bytesTransferred変数を使用できます)。

読み込み中にソケットタイムアウトがどのように発生するのか疑問に思っている場合は、read(bytes[])メソッドを呼び出すと、メッセージを含む元のパケットが分割されてしまいますが、部分的なパケットの1つがタイムアウトを超えて遅延しています(またはタイムアウトの残りの部分)。これは、_Java.io.DataInput_(readLong()readFully()BufferedReader.readLine()メソッドなどの複数バイト値の読み取りのいずれか)を実装するものに再度ラップすると、より頻繁に発生する可能性があります。

また、_Java.io.DataInputStream_は、タイムアウトの例外でも適切に動作しないため、タイムアウトのあるソケットストリームの候補としては不適切です。

2
Kevin Brock

また、InputStreamから読み取る方法にも依存します。一度に1バイトずつ文字(つまりread())を読み取る場合、BufferedInputStreamは、代わりに大量の読み取りを繰り返し実行することにより、オーバーヘッドを削減します。それを一度に4kまたは8kバイト/文字配列のブロックに読み込む場合、BuffredInputStreamはおそらくメリットがありません。

0
Paul Jowett