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

谢谢


当前回答

Though you cannot convert an OutputStream to an InputStream, java provides a way using PipedOutputStream and PipedInputStream that you can have data written to a PipedOutputStream to become available through an associated PipedInputStream. Sometime back I faced a similar situation when dealing with third party libraries that required an InputStream instance to be passed to them instead of an OutputStream instance. The way I fixed this issue is to use the PipedInputStream and PipedOutputStream. By the way they are tricky to use and you must use multithreading to achieve what you want. I recently published an implementation on github which you can use. Here is the link . You can go through the wiki to understand how to use it.

其他回答

输出流是将数据写入其中的流。如果某个模块公开了一个OutputStream,则期望在另一端有一些内容正在读取。

另一方面,公开InputStream的内容表明您将需要侦听此流,并且将有您可以读取的数据。

因此,可以将InputStream连接到OutputStream

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

正如有人提到的,这就是IOUtils的copy()方法让您做的事情。相反的方向是没有意义的。希望这能让你们理解

更新:

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

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

由于输入和输出流只是起点和终点,解决方案是将数据临时存储在字节数组中。因此,您必须创建中间ByteArrayOutputStream,从中创建字节[],用作新ByteArrayInputStream的输入。

public void doTwoThingsWithStream(InputStream inStream, OutputStream outStream){ 
  //create temporary bayte array output stream
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  doFirstThing(inStream, baos);
  //create input stream from baos
  InputStream isFromFirstData = new ByteArrayInputStream(baos.toByteArray()); 
  doSecondThing(isFromFirstData, outStream);
}

希望能有所帮助。

Though you cannot convert an OutputStream to an InputStream, java provides a way using PipedOutputStream and PipedInputStream that you can have data written to a PipedOutputStream to become available through an associated PipedInputStream. Sometime back I faced a similar situation when dealing with third party libraries that required an InputStream instance to be passed to them instead of an OutputStream instance. The way I fixed this issue is to use the PipedInputStream and PipedOutputStream. By the way they are tricky to use and you must use multithreading to achieve what you want. I recently published an implementation on github which you can use. Here is the link . You can go through the wiki to understand how to use it.

正如一些人已经回答的那样,没有有效的方法来“转换”一个OutputStream到一个InputStream。解决这类问题的技巧是将所有需要OutputStream的代码执行到它自己的线程中。通过使用管道流,我们可以将数据从创建的线程传输到InputStream中。

使用示例:

public static InputStream downloadFileAsStream(final String uriString) throws IOException {
        final InputStream inputStream = runInOwnThreadWithPipedStreams((outputStream) -> {
            try {
                downloadUriToStream(uriString, outputStream);
            } catch (final Exception e) {
                LOGGER.error("Download of uri '{}' has failed", uriString, e);
            }
        });
        return inputStream;
    }

辅助功能:

public static InputStream runInOwnThreadWithPipedStreams(
            final Consumer<OutputStream> outputStreamConsumer) throws IOException {
        final PipedInputStream inputStream = new PipedInputStream();
        final PipedOutputStream outputStream = new PipedOutputStream(inputStream);
        new Thread(new Runnable() {
            public void run() {
                try {
                    outputStreamConsumer.accept(outputStream);
                } finally {
                    try {
                        outputStream.close();
                    } catch (final IOException e) {
                        LOGGER.error("Closing outputStream has failed. ", e);
                    }
                }
            }
        }).start();
        return inputStream;
    }

单元测试:

@Test
void testRunInOwnThreadWithPipedStreams() throws IOException {

    final InputStream inputStream = LoadFileUtil.runInOwnThreadWithPipedStreams((OutputStream outputStream) -> {
        try {
            IOUtils.copy(IOUtils.toInputStream("Hello World", StandardCharsets.UTF_8), outputStream);
        } catch (final IOException e) {
            LoggerFactory.getLogger(LoadFileUtilTest.class).error(e.getMessage(), e);
        }
    });

    final String actualResult = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
    Assertions.assertEquals("Hello World", actualResult);
}

库io-extras可能很有用。例如,如果你想使用GZIPOutputStream gzip一个InputStream,并且你希望它同步发生(使用默认的缓冲区大小8192):

InputStream is = ...
InputStream gz = IOUtil.pipe(is, o -> new GZIPOutputStream(o));

请注意,该库具有100%的单元测试覆盖率(当然,这是值得的!),并且位于Maven Central上。Maven依赖项是:

<dependency>
  <groupId>com.github.davidmoten</groupId>
  <artifactId>io-extras</artifactId>
  <version>0.1</version>
</dependency>

一定要查看更新的版本。