I have a InputStream that I pass to a method to do some processing. I will use the same InputStream in other method, but after the first processing, the InputStream appears be closed inside the method.
How I can clone the InputStream to send to the method that closes him? There is another solution?
EDIT: the methods that closes the InputStream is an external method from a lib. I dont have control about closing or not.
private String getContent(HttpURLConnection con) {
InputStream content = null;
String charset = "";
try {
content = con.getInputStream();
CloseShieldInputStream csContent = new CloseShieldInputStream(content);
charset = getCharset(csContent);
return IOUtils.toString(content,charset);
} catch (Exception e) {
System.out.println("Error downloading page: " + e);
return null;
}
}
private String getCharset(InputStream content) {
try {
Source parser = new Source(content);
return parser.getEncoding();
} catch (Exception e) {
System.out.println("Error determining charset: " + e);
return "UTF-8";
}
}
If all you want to do is read the same information more than once, and the input data is small enough to fit into memory, you can copy the data from your
InputStream
to a ByteArrayOutputStream.Then you can obtain the associated array of bytes and open as many "cloned" ByteArrayInputStreams as you like.
But if you really need to keep the original stream open to receive new data, then you will need to track this external
close()
method and prevent it from being called somehow.The class below should do the trick. Just create an instance, call the "multiply" method, and provide the source input stream and the amount of duplicates you need.
Important: you must consume all cloned streams simultaneously in separate threads.
You can't clone it, and how you are going to solve your problem depends on what the source of the data is.
One solution is to read all data from the InputStream into a byte array, and then create a ByteArrayInputStream around that byte array, and pass that input stream into your method.
Edit 1: That is, if the other method also needs to read the same data. I.e you want to "reset" the stream.
Below is the solution with Kotlin.
You can copy your InputStream into ByteArray
If you need to read the
byteInputStream
multiple times, callbyteInputStream.reset()
before reading again.https://code.luasoftware.com/tutorials/kotlin/how-to-clone-inputstream/
You want to use Apache's
CloseShieldInputStream
:This is a wrapper that will prevent the stream from being closed. You'd do something like this.
This might not work in all situations, but here is what I did: I extended the FilterInputStream class and do the required processing of the bytes as the external lib reads the data.
Then you simply pass an instance of
StreamBytesWithExtraProcessingInputStream
where you would have passed in the input stream. With the original input stream as constructor parameter.It should be noted that this works byte for byte, so don't use this if high performance is a requirement.