- PR -

BufferedInputStream#available()が0をかえす

投稿者投稿内容
JBOY
ベテラン
会議室デビュー日: 2003/02/27
投稿数: 72
投稿日時: 2004-03-24 22:56
お世話になります。

掲題の件ですが、BufferedInputStream#available()が0をかえす
ことがあるということを見かけたのですが、
これは一体どういうケースの時になるのでしょうか?
もし、わかる方がいらっしゃいましたら教えて下さい。
http://java-house.jp/ml/archive/j-h-b/008795.html

[ メッセージ編集済み 編集者: JBOY 編集日時 2004-03-24 22:58 ]
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-03-24 23:57
BufferedInputStreamがラップしているInputStreamがソケットやパイプ、標準入力などの場合、バッファリングされているデータの量が0なら、available()は0を返すようです。

例えば下記のコードを実行した場合、コンソールに何か文字列を入力してEnterキーを押す(標準入力にバッファリングされているデータ量が0以上になる)まで、System.out.println("available="+bin.available())の行には到達しません。

コード:
public class Test {
	public static void main(String[] args) throws Exception{
		BufferedInputStream bin = new BufferedInputStream(System.in);
		BufferedReader in = new BufferedReader(new InputStreamReader(bin));
		while(true){
			Thread.sleep(100);
			if(bin.available() == 0)continue;
			System.out.println("available="+bin.available());
			System.out.println("echo="+in.readLine());
		}
	}
}


JBOY
ベテラン
会議室デビュー日: 2003/02/27
投稿数: 72
投稿日時: 2004-03-25 13:11
InputStreamがファイルならは起こらないということでしょうか?
コード:
byte[] buf = new byte[bis.available()];
bis.read(buf);


buf.lengthが0になることがあるのかと思っていました。
上記の参照記事はソケットやパイプの時の話なのでしょうか?
http://www.atmarkit.co.jp/fjava/rensai2/webopt07/webopt07.html
の記事にあるようにこのような事がavailable()でも起こるのかなと考えていました。
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-03-25 14:17
java.io.InputStream#available()のAPIドキュメントを読んでみると良いと思います。
ちなみに、FileInputStream#available()はnativeメソッドですので、実際に返す値はJVM側の実装によります。BufferedInputStream#available()が返す値は、「自分自身がバッファリングしているデータ量+ラップしているInputStreamのavailabe()が返す値」ですね。
佐々木
大ベテラン
会議室デビュー日: 2003/03/30
投稿数: 121
投稿日時: 2004-03-25 17:16
勘違いにより恥ずかしいことを書いていたので削除!

[ メッセージ編集済み 編集者: 佐々木 編集日時 2004-03-25 18:21 ]
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-03-26 09:37
unibon です。こんにちわ。

引用:

佐々木さんの書き込み (2004-03-25 17:16) より:
勘違いにより恥ずかしいことを書いていたので削除!

[ メッセージ編集済み 編集者: 佐々木 編集日時 2004-03-25 18:21 ]


http://www.atmarkit.co.jp/fjava/rensai2/webopt07/webopt07.html
から引用しますと、
コード:
BufferedInputStream in = 
  new BufferedInputStream( new FileInputStream( file ) );
byte[] buf = new byte[len]; 

int i;
while ( ( i = in.read( buf, 0, len ) ) != -1 ) {
  out.write( buf, 0, i) ; //outはServletOutputStream
}


と書かれている中の、BufferedInputStream でラップする必要はないと思います。これだとバッファを二重に使っていることになります。ただ、別にロジック的に悪くはないし、一般に、この程度の冗長さは BufferedInputStream の使用時に限らず、随所でおこなうものなのであまり気にしなくても良いと思います。
#ということを問われているのかな、と思ったのですが、消えてました。 が、一晩寝ながら考えたので投稿します。
JBOY
ベテラン
会議室デビュー日: 2003/02/27
投稿数: 72
投稿日時: 2004-03-26 11:43
皆様ありがとうございます。
完璧ではないですが、段々わかってきました。
ただ、いつも思うのですが、
JVMの実装次第というところがいつも気になる今日この頃です。。
佐々木
大ベテラン
会議室デビュー日: 2003/03/30
投稿数: 121
投稿日時: 2004-03-26 13:14
引用:

unibonさんの書き込み (2004-03-26 09:37) より:
unibon です。こんにちわ。

引用:

佐々木さんの書き込み (2004-03-25 17:16) より:
勘違いにより恥ずかしいことを書いていたので削除!

[ メッセージ編集済み 編集者: 佐々木 編集日時 2004-03-25 18:21 ]


http://www.atmarkit.co.jp/fjava/rensai2/webopt07/webopt07.html
から引用しますと、
コード:
BufferedInputStream in = 
  new BufferedInputStream( new FileInputStream( file ) );
byte[] buf = new byte[len]; 

int i;
while ( ( i = in.read( buf, 0, len ) ) != -1 ) {
  out.write( buf, 0, i) ; //outはServletOutputStream
}


と書かれている中の、BufferedInputStream でラップする必要はないと思います。これだとバッファを二重に使っていることになります。ただ、別にロジック的に悪くはないし、一般に、この程度の冗長さは BufferedInputStream の使用時に限らず、随所でおこなうものなのであまり気にしなくても良いと思います。
#ということを問われているのかな、と思ったのですが、消えてました。 が、一晩寝ながら考えたので投稿します。



そのとおりです。「自分でバッファリングするならBufferedInputStreamを使う意味はない」ということを言いたかったのです。

それをなぜ消したかと言えばですね。
ぼくはこういう場合、BufferedInputStreamの性能を信じ切って1バイト単位のread()をよく使うのですが、計測してみるとこれが自前バッファリングより10倍近く遅かったわけです(生の1バイトread()よりは50倍以上速いのですが)。そういうわけで、「確かめもせずに適当なことを書いてしまったなぁ」と反省して削除したわけでした。

ま、しかし、あのコードが妙であるということは確かですね。

まとめると、
* 自分でバッファリングするならBuffered*でくるむ必要はない。
* しかし、Buffered*でくるんだからといってint read()はやはりちょっと重い。(ここが僕の勘違いポイントでした。充分速いと思っていた。)
ということです。

ちなみに計測条件と結果は以下のようなものです。

テスト概要: 21.2MBのファイルを読み込むのに要する時間を計測。
OS: Windows2000
JDK: IBM製の1.3
結果:
(1) バッファリング無しの1バイトread(): 38578ms
(2) BufferedInputStreamでの1バイトread() 578ms
(3) 自前で1024バイトのバッファを使ってread(byte[]) 62ms

スキルアップ/キャリアアップ(JOB@IT)