0

I'm trying to get a copy of the content from the stream without consuming it. My plan is to use this original stream in the later of the code. Following is the sample code I tried to check this. My intention is to keep the original InputStream for future use after getting a copy

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamTest {

public static void main(String[] args) {
    try {
        InputStream inputstream = new FileInputStream("resource.txt"); // content of the file is 'test'

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        org.apache.commons.io.IOUtils.copy(inputstream, baos);
        byte[] bytes = baos.toByteArray();
        System.out.println("copied stream    : " + new String(bytes));

        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(inputstream));
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line + System.lineSeparator());
        }
        System.out.println("original stream  : " + sb.toString());
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

but still, when I access the original stream, after coping it, I still see that the original stream is consumed. See below output

copied stream    : test
original stream  : 

Can someone point out my mistake

Thanks

Chamila Adhikarinayake
  • 3,588
  • 5
  • 25
  • 32
  • Use `.mark()` before and then `.reset()`. – Johannes Kuhn Apr 01 '20 at 07:19
  • Of course it's consumed. You consumed it. This is a non-issue. All you have to to do read it again is to call `new FileInputStream()` again. Not forgetting to close them both. Or construct a `ByteArrayInputStream` from the `ByteArrayOutputStream`. – user207421 Apr 01 '20 at 07:19
  • Does this answer your question? [How to clone an InputStream?](https://stackoverflow.com/questions/5923817/how-to-clone-an-inputstream) – Aymen Apr 01 '20 at 07:20
  • 1
    @JohannesKuhn `FileInputStream.mark()` isn't supported. – user207421 Apr 01 '20 at 07:23
  • @user207421 this is just a sample (reading the file) . my question is how to do it without creating a new stream from the original source agai – Chamila Adhikarinayake Apr 01 '20 at 07:25
  • And my answer is that you can't, and that you don't need to. – user207421 Apr 01 '20 at 07:27
  • @Aymen not really. in that answer, the original stream is still consumed. what I'm trying to do is to keep the original stream as it is. thanks btw – Chamila Adhikarinayake Apr 01 '20 at 07:36
  • Which is exactly what you cannot do. Your question embodies a contradiction in terms. And what exactly is the point? How many nanoseconds do you need to save here? – user207421 Apr 01 '20 at 07:37
  • @user207421 This is what i'm trying to achieve. I have an existing program that consumes input stream. my plan is to log the content of this stream without consuming it so that the rest of the program can work with the original stream. do u have any solution for that. Also i cannot change the existing program. – Chamila Adhikarinayake Apr 01 '20 at 07:42
  • 2
    @matt OP is talking about `InputStream`s not Java 8 `Stream`s – Lino Apr 01 '20 at 07:56
  • @Lino thanks! Chamila there are stream wrappers you can use, such as the FilterInputStream, that might be what you're after? – matt Apr 01 '20 at 07:57
  • Since you're using the a reader, check out the [LineNumberReader](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/LineNumberReader.html) it extends BufferedReader. You could make a similar class, so that as your read from it, it reads from the original BufferedReader, logs the values and returns them. – matt Apr 01 '20 at 08:06
  • Does this answer your question? Or this: https://stackoverflow.com/a/34955334/2067492 – matt Apr 01 '20 at 08:11
  • This is simply not possible, you can't copy the stream without consuming it. – Mark Rotteveel Apr 01 '20 at 18:25

1 Answers1

3

Sadly this is not possible by the nature of streams.

In order to copy the data from the stream, you need to first extract it. By extracting it, you consume the stream.

But do not worry, there should be a solution for your specific use case. Maybe open another stream (if you know the source of the stream gives the same data every time - as in a file - , you can use Supplier everywhere you would use the InputStream, so that a new stream is created whenever necessary), or you can check out this post for creating more streams with the same data: https://stackoverflow.com/a/5924132/3102234

Horațiu Udrea
  • 1,727
  • 8
  • 14
  • Thanks for taking time to answer. Unfortunately opening another InputStream is not possible (above code section is to plug in to a web service and InputStream is coming from the request done to this service. Above code is a sample to check this behaviour). And for the SO link , still the original stream is consumed so guess it is not working for my situation as well. – Chamila Adhikarinayake Apr 01 '20 at 08:41