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.
精彩评论