如何将输出流转换为输入流?

新手上路,请多包涵

我正处于开发阶段,我有两个模块,从一个模块中我得到了 OutputStream 和第二个模块的输出,它只接受 InputStream 。你知道如何将 OutputStream 转换为 InputStream (反之亦然,我的意思是这样)我将能够连接这两个部分?

谢谢

原文由 Waypoint 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

OutputStream 是您写入数据的地方。如果某个模块公开了 OutputStream ,则期望在另一端有读取内容。

另一方面,暴露 InputStream 的东西表明您将需要收听此流,并且会有您可以读取的数据。

因此可以将 InputStream 连接到 OutputStream

InputStream----read---> intermediateBytes[n] ----write----> OutputStream

正如有人提到的,这就是 IOUtils 的 — copy() 方法可以让你做的事情。走另一条路是没有意义的……希望这是有道理的

更新:

当然,我想得越多,我就越能看到这实际上是一个要求。我知道提到的一些评论 Piped 输入/输出流,但还有另一种可能性。

如果公开的输出流是 ByteArrayOutputStream ,那么您始终可以通过调用 toByteArray() 方法来获取完整内容。然后,您可以使用 ByteArrayInputStream 子类创建输入流包装器。这两个是伪流,它们基本上都只是包装一个字节数组。因此,以这种方式使用流在技术上是可行的,但对我来说仍然很奇怪……

原文由 Java Drinker 发布,翻译遵循 CC BY-SA 3.0 许可协议

似乎有很多链接和其他类似的东西,但没有使用管道的实际代码。使用 java.io.PipedInputStreamjava.io.PipedOutputStream 的优点是没有额外的内存消耗。 ByteArrayOutputStream.toByteArray() 返回原始缓冲区的副本,这意味着无论你在内存中有什么,你现在都有它的两个副本。然后写入 InputStream 意味着您现在拥有数据的三个副本。

使用 lambdas 的代码(来自评论的@John Manko 的提示):

 PipedInputStream in = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(in);
// in a background thread, write the given output stream to the
// PipedOutputStream for consumption
new Thread(() -> {originalOutputStream.writeTo(out);}).start();

@John Manko 指出的一件事是,在某些情况下,当您无法控制 OutputStream 的创建时,您最终可能会遇到创建者可能过早清理 OutputStream 对象的情况。如果你得到 ClosedPipeException ,那么你应该尝试反转构造函数:

 PipedInputStream in = new PipedInputStream(out);
new Thread(() -> {originalOutputStream.writeTo(out);}).start();

请注意,您也可以反转以下示例的构造函数。

还要感谢@AlexK 纠正我开始 Thread 而不是仅仅开始 Runnable


使用 try-with-resources 的代码:

 // take the copy of the stream and re-write it to an InputStream
PipedInputStream in = new PipedInputStream();
    new Thread(new Runnable() {
        public void run () {
            // try-with-resources here
            // putting the try block outside the Thread will cause the
            // PipedOutputStream resource to close before the Runnable finishes
            try (final PipedOutputStream out = new PipedOutputStream(in)) {
                // write the original OutputStream to the PipedOutputStream
                // note that in order for the below method to work, you need
                // to ensure that the data has finished writing to the
                // ByteArrayOutputStream
                originalByteArrayOutputStream.writeTo(out);
            }
            catch (IOException e) {
                // logging and exception handling should go here
            }
        }
    }).start();


我写的原始代码:

 // take the copy of the stream and re-write it to an InputStream
PipedInputStream in = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(in);
new Thread(new Runnable() {
    public void run () {
        try {
            // write the original OutputStream to the PipedOutputStream
            // note that in order for the below method to work, you need
            // to ensure that the data has finished writing to the
            // ByteArrayOutputStream
            originalByteArrayOutputStream.writeTo(out);
        }
        catch (IOException e) {
            // logging and exception handling should go here
        }
        finally {
            // close the PipedOutputStream here because we're done writing data
            // once this thread has completed its run
            if (out != null) {
                // close the PipedOutputStream cleanly
                out.close();
            }
        }
    }
}).start();

此代码假定 originalByteArrayOutputStream 是一个 ByteArrayOutputStream 因为它通常是唯一可用的输出流,除非您正在写入文件。这样做的好处在于,因为它在一个单独的线程中,所以它也是并行工作的,所以无论什么消耗你的输入流,都会从你的旧输出流中流出。这是有益的,因为缓冲区可以保持更小并且您将拥有更少的延迟和更少的内存使用。

If you don’t have a ByteArrayOutputStream , then instead of using writeTo() , you will have to use one of the write() methods in the java.io.OutputStream 类或子类中可用的其他方法之一。

原文由 mikeho 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题