Java将OutputStream转为InputStream
遇见的问题:做文件处理时,有两个工具类,一个是生成文件,需要一个OutputStream来写出,一个是上传文件,需要一个InputStream来读取
类似代码:
// wordObj处理之后需要写出到一个输出流中
wordObj.write(OutputStream out);
// ...
// 工具类B读取一个输入流
UtilB.read(InputStream in);
使用File类进行转换
第一种方法是wordObj
将文件写出到一个临时目录,UtilB
读取之后再将临时文件删除,这种方式是最慢的,需要访问硬盘进行读写。
使用ByteArrayStream类进行转换
第二种方法是使用ByteArrayStream
进行转换,这种方法会将写出的文件保存在内存中,然后被工具类读取,伪代码如下:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 写入
wordObj.write(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// 读取
UtilB.read(bais);
这种方式比较简单,缺点是比较占用内存,而且数据需要在内存中复制来复制去,效率不够高。
(重点)使用PipedStream类进行转换
参考StackOverFlow高赞回答,根据实际情况进行了修改
PipedInputStream pipedInputStream = new PipedInputStream();
final CountDownLatch cdl = new CountDownLatch(1);
// 使用PipedStream时不能在同一个线程
// 这里使用了hutool的全局线程池,直接((Runnable)() -> {}).start()也可以
ThreadUtil.execute(() -> {
try (PipedOutputStream pipedOutputStream = new PipedOutputStream(pipedInputStream)) {
cdl.countDown();
wordObj.write(pipedOutputStream);
} catch (IOException e) {
e.printStackTrace();
}
});
// 等待输出管道准备好时再开始读取输入管道
cdl.await();
// 读取
UtilB.read(pipedInputStream);
这种方式的优点是不占用内存,并且效率更高,没有数据在内存中拷来拷去,缺点是更加复杂了