我有一个需要读取的OutputStream,因此我使用以下(Groovy)代码来获取对数据的InputStream引用:
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)
在这种情况下,handler是一个实现具有此方法的接口的类:
public void process(InputStream stream);
我们的新要求中出现的问题是流上有一些预处理,因此我需要在handler.process()方法中至少读取两次流.以下是一个实现的一些示例代码:
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 MB的限制或Integer.MAX_VALUE缓冲区大小.但是,我总是得到以下异常:
java.io.IOException: Stream closed
这甚至可能吗?我认为问题是关闭PipedOutputStream的线程,但我不知道如何防止这种情况,或者我是否因为在Java Stream IO中成为新手而创建了更多问题.
最佳答案 我最好的猜测是你的parseMetadata以某种方式关闭了流.我已经尝试了你的方案,它对我来说很好.通常,在处理程序完成读取之前关闭OutputStream不是问题,这正是管道流的用途.
此外,根据您的情况,我会省略管道和附加线程.如果您不介意将整个流存储在内存中,您可以执行类似的操作
ByteArrayOutputStream out = new ByteArrayOutputStream();
fillTheOutput(out);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
pass1(in);
in.reset();
pass2(in);
如果你介意在内存中拥有所有内容,那么无论如何你都会遇到麻烦,因为你的BufferedInputStream大致相同.
编辑:请注意,您可以根据字节数组轻松构建新的ByteArrayInputStream,这是常规流无法做到的.