0

Is there any way to convert an OutputStream into an InputStream?

So the following would work

InputStream convertOStoIS(OutputStream os) {

}

I do not want to use any libraries, I read that there are some who are able to accomplish this with bytecode manipulation.

Edit

I want to be able to intersect a sink, to analyze the data or redirect the output. I want to place another OutputStream under the on given by some function and redirect the data into another input stream.

The related topics had a ByteArrayOutputStream or a PipedStream which is not the case in my question.

Related:

halfer
  • 19,824
  • 17
  • 99
  • 186
Feirell
  • 719
  • 9
  • 26
  • The question is very unclear. Do you mean you want to write some data and then read it back? If not, what does it actually mean to "convert an OutputStream to an InputStream"? What do you want to do before and after you do that that requires that conversion? Please clarify. – Jim Garrison Feb 08 '18 at 18:47
  • @rmlan please read the answer fully, especially the "Update" – Feirell Feb 08 '18 at 19:24
  • @JimGarrison edited the question – Feirell Feb 08 '18 at 19:28
  • 1
    Did you look at `java.io.FilterOutputStream`? This will allow you to wrap any `OutputStream` and examine/modify the data as it is being written. – Jim Garrison Feb 08 '18 at 19:31
  • @JimGarrison sadly I can only apply this on top not underneath. This would solve my problem if I was able to tell an already created `OutputStream` to discard the old output and use a custom filter stream instead. – Feirell Feb 08 '18 at 19:45
  • @JimGarrison no stop you are right! This will solve my problem! Could you please answer this question. Thank you! Btw. is there anyway to replace the sink of an already created `OutputStream`? – Feirell Feb 08 '18 at 19:49

2 Answers2

1

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.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
  • I would not need the data to move but just to be able to redirect it. Even if the question is not answered, this solves my initial problem. – Feirell Feb 08 '18 at 20:09
1

To answer my own question, yes you can build a redirect like this:

class OutInInputRedirect {
    public final transient InputStream is;
    public final transient OutputStream os;

    public OutInInputRedirect() throws IOException {
        this(1024);
    }

    public OutInInputRedirect(int size) throws IOException {
        PipedInputStream is = new PipedInputStream(size);
        PipedOutputStream os = new PipedOutputStream(is);

        this.is = is;
        this.os = os;
    }
}

Just use the OutputStream as an replacement and the InputStream in those places you need, be awere that the closing of the OutputStream also closes the InputStream!

It is quite easy and works as expected. Either way you cannot change an already connected stream (without reflection).

Feirell
  • 719
  • 9
  • 26
  • 1
    According to documentation this solution is dangerous and can cause a deadlock, because it is run from the same thread, reference: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/PipedInputStream.html – h3wro Aug 04 '22 at 11:58