chanting an air of joyous bliss

普段の生活で見逃しがちな面白いことを書いていく
そんなブログです

BufferedInputStreamの#availableメソッドについて

2015-01-21 22:37:11 | Java

Javaでディバイス上の画像ファイルをメモリに読み込むときは普通以下のような手順を踏む
1.BufferedInputStreamを使って入力ストリームを生成する
2.ByteArrayOutputStreamを使って出力ストリームを生成する
3.1.で生成したBufferedInputStreamに対してreadメソッドを実行し、バイト配列を取得する
4.3.で取得したバイト配列をByteArrayOutputStreamのwriteメソッドを使って出力ストリームに書き出す
5.BufferedInputStream#readメソッドが-1を返すまで、3と4の処理を続ける
6.ByteArrayOutputStream# toByteArray()を用いてバイト配列を取得する
ご覧の通りディバイス上のファイルをメモリに読み込むときはそれなりに面倒くさい手順を踏む必要がある
先日、私が携わっているシステムで Javaでディバイス上のファイルをメモリに読み込む処理を以下のように実装していたソースがあった
1.BufferedInputStreamを使って入力ストリームを生成する
2.BufferedInputStream#availableメソッドを使用してバッファー上にあるバイト数を取得する
3.2.で取得した数値分、バイト配列を確保する
4.BufferedInputStream#readメソッドに3.で設定したバイト配列を指定して実行する。そうするとバイト配列にデータが書き込まれる
BufferedInputStream#availableメソッドを使うこの方法、世間一般的な方法に比べて、面倒なループも実装ステップ数も短くってエレガント!
・・・と実装した人は思ったに違いないが・・・
ある日、お客様から
「ごくまれに壊れた画像データが表示される」
というクレームがきた
クレームが来た処理はBufferedInputStream#availableメソッドを使う方法を使っているソースだった。
BufferedInputStream#availableメソッドを使う方法はあまり一般的ではない、ということもあり念のためJavaDocでavailableの仕様を確認したところ・・

この入力ストリームのメソッドの次の呼び出しによって、ブロックせずにこの入力ストリームから読み込むことができる (またはスキップできる) 推定バイト数を返します。
次の呼び出しは、同じスレッドの場合も別のスレッドの場合もあります。このような多数のバイトを 1 回で読み込んだりスキップしたりすることでブロックすることはありませんが、読み込むまたはスキップするバイト数が少なくなることがあります。  
このメソッドは、バッファーの中に残っている読み込み可能なバイトの総数 (count - pos) を返し、in.available() 呼び出しの結果を返します。

ん?この記述っぷりからすると、BufferedInputStream#availableはファイルの全バイト数を取得することを保証していないのでは?
という疑問が沸き起こり、親クラスのInputStream#availableの記述を見ると・・・

この入力ストリームのメソッドの次の呼び出しによって、ブロックせずにこの入力ストリームから読み込むことができる (またはスキップできる) 推定バイト数を返します。
次の呼び出しは、同じスレッドの場合も別のスレッドの場合もあります。
このような多数のバイトを 1 回で読み込んだりスキップしたりすることでブロックすることはありませんが、読み込むまたはスキップするバイト数が少なくなることがあります。
InputStream の実装には、ストリームの合計バイト数を返すものもありますが、多くの実装は返さないことに注意してください。
このストリームのデータをすべて保持するためのバッファーを割り当てるのに、このメソッドの戻り値を使用することは、適切ではありません。


やっぱり、
BufferedInputStream#availableはファイルの全バイト数を取得することを保証していない
ではないか!
お客様からクレームの来た「壊れた画像」ができた理由は
というのはまだ読み込むべきデータがあったけれど、それを取得せずに中途半端な状態のまま画像を表示した結果
だということか!

(今回の教訓)
あるロジックを実装するときは世間一般のやり方を踏襲しよう!
もし、世間一般のやり方を踏襲できない場合はJavaDocをちゃんと見なければならない!

コメント    この記事についてブログを書く
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« H2604 午後2 問1について | トップ | ARIA The AVVENIRE »
最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。

Java」カテゴリの最新記事