Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert OutputStream to InputStream?

I am on the stage of development, where I have two modules and from one I got output as a OutputStream and second one, which accepts only InputStream. Do you know how to convert OutputStream to InputStream (not vice versa, I mean really this way) that I will be able to connect these two parts?

Thanks

like image 594
Waypoint Avatar asked Apr 25 '11 13:04

Waypoint


People also ask

How do I get InputStream from OutputStream?

transferTo() Method. In Java 9 or higher, you can use the InputStream. transferTo() method to copy data from InputStream to OutputStream . This method reads all bytes from this input stream and writes the bytes to the given output stream in the original order.

How do I convert String to InputStream?

We can convert a String to an InputStream object by using the ByteArrayInputStream class. This class constructor takes the string byte array which can be done by calling the getBytes() method of a String class.

What is the difference between InputStream and OutputStream?

The InputStream is used to read data from a source and the OutputStream is used for writing data to a destination.


2 Answers

There seem to be many links and other such stuff, but no actual code using pipes. The advantage of using java.io.PipedInputStream and java.io.PipedOutputStream is that there is no additional consumption of memory. ByteArrayOutputStream.toByteArray() returns a copy of the original buffer, so that means that whatever you have in memory, you now have two copies of it. Then writing to an InputStream means you now have three copies of the data.

The code:

// 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(); 

This code assumes that the originalByteArrayOutputStream is a ByteArrayOutputStream as it is usually the only usable output stream, unless you're writing to a file. I hope this helps! The great thing about this is that since it's in a separate thread, it also is working in parallel, so whatever is consuming your input stream will be streaming out of your old output stream too. That is beneficial because the buffer can remain smaller and you'll have less latency and less memory usage.

like image 142
mikeho Avatar answered Oct 06 '22 10:10

mikeho


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...

like image 33
Java Drinker Avatar answered Oct 06 '22 11:10

Java Drinker