从输出流创建输入流的最有效方法

本页:http://blog.ostermiller.org/convert-java-outputstream-inputstream 介绍如何从输出流创建输入流:

new ByteArrayInputStream(out.toByteArray())

其他替代方法是使用管道流和新线程,这很麻烦。

我不喜欢将许多兆字节复制到新的内存字节数组的想法。有没有一个库可以更有效地做到这一点?

编辑:

根据Laurence Gonsalves的建议,我尝试了PipedStreams,结果发现它们并不难处理。下面是 clojure 中的示例代码:

(defn #^PipedInputStream create-pdf-stream [pdf-info]
  (let [in-stream (new PipedInputStream)
        out-stream (PipedOutputStream. in-stream)]
    (.start (Thread. #(;Here you write into out-stream)))
    in-stream))

答案 1

如果您不想一次将所有数据复制到内存中缓冲区,那么您必须让使用 OutputStream(生产者)的代码和使用 InputStream(使用者)的代码在同一线程中交替,或者在两个单独的线程中并发操作。让它们在同一线程中运行可能比使用两个单独的线程要复杂得多,更容易出错(你需要确保使用者永远不会阻塞等待输入,否则你将有效地死锁),并且需要让生产者和消费者在同一个循环中运行,这似乎太紧密耦合了。

因此,请使用第二个线程。它真的没有那么复杂。您链接到的页面有合理的例子。这是一个有点现代化的版本,它也关闭了流:

try (PipedInputStream in = new PipedInputStream()) {
    new Thread(() -> {
        try (PipedOutputStream out = new PipedOutputStream(in)) {
            writeDataToOutputStream(out);
        } catch (IOException iox) {
            // handle IOExceptions
        }
    }).start();
    processDataFromInputStream(in);
}

答案 2

还有另一个名为EasyStream的开源库,它以透明的方式处理管道和螺纹。如果一切顺利,这并不复杂。问题出现的时候(看看劳伦斯·贡萨尔维斯的例子)

class1.putDataOnOutputStream(out);

引发异常。在该示例中,线程只是完成,异常丢失,而外部线程可能会被截断。InputStream

Easystream处理异常传播和其他令人讨厌的问题,我已经调试了大约一年。(我是图书馆的管理员:显然我的解决方案是;)最好的)以下是有关如何使用它的示例:

final InputStreamFromOutputStream<String> isos = new InputStreamFromOutputStream<String>(){
 @Override
 public String produce(final OutputStream dataSink) throws Exception {
   /*
    * call your application function who produces the data here
    * WARNING: we're in another thread here, so this method shouldn't 
    * write any class field or make assumptions on the state of the outer class. 
    */
   return produceMydata(dataSink)
 }
};

还有一个很好的介绍,其中解释了将输出流转换为输入流的所有其他方法。值得一看。


推荐