Convert an OutputStream into an InputStream (Reference)

Here we are assuming you already know it's not an easy problem, and you are prepared to go for the hard way because the easy solutions don't fit your needs for performance and memory usage. If you came here at first and you don't understand why this is so complicated you can have a look at this preamble.

This library provides two ways to do this task that are equivalent.


This is an abstract class that extends InputStream, users must extend this abstract class and implement the abstract method produce(OutputStream). This function is called back by the library when the InputStreamFromOutputStream is used. The library pass an OutputStream as a parameter and the user should produce its data inside the produce() method, and write it to the supplied OutputStream. The data is then available for reading through the InputStreamFromOutputStream (outer) class.

Sample usage:

final String dataId=//id of some data.
try(final InputStreamFromOutputStream<String> isOs = new InputStreamFromOutputStream<String>() {
	protected String produce(final OutputStream dataSink) throws Exception {
 	 	 * call the function who produces the data (writes to the OutputStream).
 	 	 * produceMyData is a function of the software callign the library.
 	 	 * in this case it is supposed to return a String (not necessary). 
         * WARNING: we're in another thread here, so this method shouldn't 
         * write any class field or make assumptions on the state of the class.
		return produceMydata(dataId, dataSink);
}) {		
	//here you can read from the InputStream the data that was previously written to the 
	//dataSink OutputStream (the usage of is merely an example)
	byte[] read=IOUtils.toByteArray( isOs );
	//You can use the data here ...
	//Optional: you can get the return value of produceMyData after the InputStream has been fully read.
	String resultOfProduction = isOs.getResult();
} catch (final IOException e) {
	//Handle exceptions here

Some programmers might be unfamiliar with the syntax of this example. The variable isOs is an anonymous inner class that overrides the method produce(OutputStream). The anonymous subclassing is made inside a "try with resources" structure that takes care of closing the stream automatically. You can still use standard inheritance if you prefer. Or, if you're not familiar with the "try with resources" syntax you can have a look at the java 6 examples.

As discussed earlier the method produce is called by another thread created internally by the library. If you want to know more about the way this library creates threads have a look at the ExecutionModel wiki page. For further information read the api javadoc.


Another class that you can use if you need to write to an OutputStream and read the data written from an InputStream is OutputStreamToInputStream . It works in the opposite direction to previous one: it is a subclass of OutputStream, you can write your data to. The function doRead is called and data can be read from the InputStream passed as a parameter. It also allow some result to be returned after the processing of the InputStream.

Sample usage:

try (final OutputStreamToInputStream<String> os2is = new OutputStreamToInputStream<String>() {
    protected String doRead(final InputStream istream) throws Exception {
         / *
           * Read the data from the InputStream "istream" passed as parameter. 
           * The data you read here is the one that will be written later in 
           * "oStream2IStream.write()". In this case it is the string "test". 
           * You should implement your own processing function (the usage of 
           * here is merely an example).
           final String result = IOUtils.toString(istream);
           // after the data has been processed you may optionally want to return a result.
           // this can be used in the method "getResult()". The following code is an example too.
           return result + " was processed.";
}) {
	 * put here the code that writes to the OutputStream, the data will be 
	 * passed to the method doRead(InputStream i) above.
	 //Optional: when the os2is has been fully written you can retrieve the object returned by the method "doRead()".
	 String result = oStream2IStream.getResult();
	 //result now contains the string "test was processed."

This class propagates the !Exception from the internal doRead() to the external OutputStream, and closing the oStream2IStream OutputStream will cause an EOF on the InputStream passed as doRead() parameter.

If you're not familiar with the "try with resources" syntax you can have a look at the java 6 examples. For further information see the api javadoc.