How to Convert Outputstream to Inputstream

How to convert OutputStream to InputStream?

An OutputStream is one where you write data to. If some module exposes an OutputStream, the expectation is that there is something reading at the other end.

Something that exposes an InputStream, on the other hand, is indicating that you will need to listen to this stream, and there will be data that you can read.

So it is possible to connect an InputStream to an OutputStream

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

As someone metioned, this is what the copy() method from IOUtils lets you do. It does not make sense to go the other way... hopefully this makes some sense

UPDATE:

Of course the more I think of this, the more I can see how this actually would be a requirement. I know some of the comments mentioned Piped input/ouput streams, but there is another possibility.

If the output stream that is exposed is a ByteArrayOutputStream, then you can always get the full contents by calling the toByteArray() method. Then you can create an input stream wrapper by using the ByteArrayInputStream sub-class. These two are pseudo-streams, they both basically just wrap an array of bytes. Using the streams this way, therefore, is technically possible, but to me it is still very strange...

Most efficient way to create InputStream from OutputStream

If you don't want to copy all of the data into an in-memory buffer all at once then you're going to have to have your code that uses the OutputStream (the producer) and the code that uses the InputStream (the consumer) either alternate in the same thread, or operate concurrently in two separate threads. Having them operate in the same thread is probably much more complicated that using two separate threads, is much more error prone (you'll need to make sure that the consumer never blocks waiting for input, or you'll effectively deadlock) and would necessitate having the producer and consumer running in the same loop which seems way too tightly coupled.

So use a second thread. It really isn't that complicated. The page you linked to had reasonable example. Here's a somewhat modernized version, which also closes the streams:

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

converting OutputStream into an InputStream

Use a java.io.FilterOutputStream to wrap the existing OutputStream. By overriding the write() method you can intercept output and do whatever you want with it, either send it somewhere else, modify it, or discard it completely.

As to your second question, you cannot change the sink of an OutputStream after the fact, i.e. cause previously written data to "move" somewhere else, but using a FilterOutputStream you can intercept and redirect any data written after you wrap the original `OutputStream.

convert ByteArrayOutputStream to FileInputStream

You can create a ByteArrayInputStream with

InputStream is = new ByteArrayInputStream(bos.toByteArray());

and then read from this InputStream.

If your interface only accepts a FileInputStream then the interface is broken...

If, at all, an interface only works with files it should accept a File else it should use an InputStream.

Also if you use threads you can use PipedInputStream and PipedOutputStream directly between the threads.

Byte[] to InputStream or OutputStream

You create and use byte array I/O streams as follows:

byte[] source = ...;
ByteArrayInputStream bis = new ByteArrayInputStream(source);
// read bytes from bis ...

ByteArrayOutputStream bos = new ByteArrayOutputStream();
// write bytes to bos ...
byte[] sink = bos.toByteArray();

Assuming that you are using a JDBC driver that implements the standard JDBC Blob interface (not all do), you can also connect a InputStream or OutputStream to a blob using the getBinaryStream and setBinaryStream methods1, and you can also get and set the bytes directly.

(In general, you should take appropriate steps to handle any exceptions, and close streams. However, closing bis and bos in the example above is unnecessary, since they aren't associated with any external resources; e.g. file descriptors, sockets, database connections.)

1 - The setBinaryStream method is really a getter. Go figure.

Easy way to write contents of a Java InputStream to an OutputStream

Java 9

Since Java 9, InputStream provides a method called transferTo with the following signature:

public long transferTo(OutputStream out) throws IOException

As the documentation states, transferTo will:

Reads all bytes from this input stream and writes the bytes to the
given output stream in the order that they are read. On return, this
input stream will be at end of stream. This method does not close
either stream.

This method may block indefinitely reading from the
input stream, or writing to the output stream. The behavior for the
case where the input and/or output stream is asynchronously closed, or
the thread interrupted during the transfer, is highly input and output
stream specific, and therefore not specified

So in order to write contents of a Java InputStream to an OutputStream, you can write:

input.transferTo(output);

Convert OutputStream to ByteArrayOutputStream

There are multiple possible scenarios:

a) You have a ByteArrayOutputStream, but it was declared as OutputStream. Then you can do a cast like this:

void doSomething(OutputStream os)
{
// fails with ClassCastException if it is not a BOS
ByteArrayOutputStream bos = (ByteArrayOutputStream)os;
...

b) if you have any other type of output stream, it does not really make sense to convert it to a BOS. (You typically want to cast it, because you want to access the result array). So in this case you simple set up a new stream and use it.

void doSomething(OutputStream os)
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(something);
bos.close();
byte[] arr = bos.toByteArray();
// what do you want to do?
os.write(arr); // or: bos.writeTo(os);
...

c) If you have written something to any kind of OutputStream (which you do not know what it is, for example because you get it from a servlet), there is no way to get that information back. You must not write something you need later. A solution is the answer b) where you write it in your own stream, and then you can use the array for your own purpose as well as writing it to the actual output stream.

Keep in mind ByteArrayOutputStreams keep all Data in Memory.



Related Topics



Leave a reply



Submit