遇见的问题:做文件处理时,有两个工具类,一个是生成文件,需要一个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);

这种方式的优点是不占用内存,并且效率更高,没有数据在内存中拷来拷去,缺点是更加复杂了

标签: Java

添加新评论