2011-02-09 5 views
4

で持つPipedInputStreamラッピング私はから読み取るために必要なOutputStreamを有し、そして私はデータ入力ストリーム参照を取得するために、次の(グルービー)コードを使用する:この場合、BufferedInputStreamを

PipedInputStream inputStream = new PipedInputStream() 
    PipedOutputStream outputStream = new PipedOutputStream(inputStream) 
    new Thread(
      new Runnable() { 
       public void run() { 
        // Some API method 
        putDataInOutputStream(outputStream) 
        outputStream.close() 
       } 
      } 
    ).start() 

handler.process(inputStream) 

をハンドラは、このメソッドを持つインタフェースを実装するいくつかのクラスである:

public void process(InputStream stream); 

私たちの新たな要件に思い付いた問題は、いくつかの前処理がストリームにあったということでしたので、私は時の流れを読む必要handler.process()メソッドで少なくとも2回。ここでは一の実施からいくつかのサンプルコードです。

public void process(InputStream stream) { 
    def bufferedStream = new BufferedInputStream(stream, 30 * 1048576) // 30 MB 
    bufferedStream.mark(Integer.MAX_VALUE) 
    parseMetadata(bufferedStream) 
    bufferedStream.reset() 
    doTheThingYouDo(bufferedStream) 
} 

私はいくつかの入力のために、私は30メガバイトの制限またはInteger.MAX_VALUEのバッファサイズを打つないだということを知っています。しかし、私はいつも次の例外が発生しています:

java.io.IOException: Stream closed 

これも可能ですか?私は問題がPipedOutputStreamのスレッドを閉じていると思うが、それを防ぐ方法がわからない、あるいはおそらくJava Stream IOの初心者であることによってさらに問題を引き起こしているのだろうか。

答えて

2

あなたのparseMetadataさんが何とかストリームを終了したと思います。私はあなたのシナリオを試しました、それは私のために正常に動作します。一般的に、ハンドラが読み込みを終了する前にOutputStreamを閉じることは問題ではありません。それはまさにパイプされたストリームのためです。

さらに、あなたの状況を考えれば、私は配管と追加のスレッドを省きます。あなたがメモリ内にあなたの全体の流れを持つ気にしない場合は、

ByteArrayOutputStream out = new ByteArrayOutputStream(); 

fillTheOutput(out); 

ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 

pass1(in); 
in.reset(); 
pass2(in); 

ような何かを行うことができますが、メモリ内のすべてを持つ心をすれば、あなたのBufferedInputStreamは大体同じことをしているので、あなたは、とにかくトラブルにいます。

編集:通常のストリームでは不可能なバイト配列に基づいて、新しいByteArrayInputStreamを簡単に作成できます。

+0

はい、バッファリングされた入力ストリームに関する良い点です。いずれにしても、ヒープが巨大になる可能性があります。これらのバッファ/バイト配列のサイズは数百MBであり、同時に多数の処理が可能です。テーブルのもう1つのオプションは、2度読み込むための作業ファイルですが、おそらくバイト配列を1回取得し、必要に応じて使用する方が良いでしょう。 – Greymeister

関連する問題