开发者

Wrapping a PipedInputStream with a BufferedInputStream

开发者 https://www.devze.com 2023-02-10 02:46 出处:网络
I have an OutputStream that I needed to read from, and so I used the following (Groovy) code to get an InputStream reference to the data:

I have an OutputStream that I needed to read from, and so I used the following (Groovy) code to get an InputStream reference to the data:

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)

In this case, handler is some class that implements an interface which has this method:

public void process(InputStream stream);

The problem that came up in our new requirements was that there was some pre-processing on the stream, and therefore I need to read the stream at least twice in the handler.process() method. Here's some example code from one implementation:

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)
 }

I know that for some input I am not hitting the 30 MB limit or the Integer.MAX_VALUE buffer size. However, I'm always getting the following exception:

jav开发者_开发技巧a.io.IOException: Stream closed

Is this even possible? I think the problem is the thread closing on the PipedOutputStream, but I don't know how to prevent that or if perhaps I'm creating more problems by being a novice at Java Stream IO.


My best guess is that your parseMetadata somehow closed the stream. I've tried your scenario, and it works fine for me. In general, closing the OutputStream before your handler is done reading is not the problem, that's exactly what the piped streams are for.

Besides, given your situation, I would leave out the piping, and the additional thread. If you don't mind having your entire stream in memory, you can do something like

ByteArrayOutputStream out = new ByteArrayOutputStream();

fillTheOutput(out);

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

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

If you do mind having everything in memory, you're in trouble anyway, since your BufferedInputStream does roughly the same thing.

edit: Note that you can easily build a new ByteArrayInputStream based on the byte array, which is something you cannot do with regular streams.

0

精彩评论

暂无评论...
验证码 换一张
取 消