Sunday, May 23, 2021

ResetOnCloseStream or ReusableInputStream.

Reading an input stream multiple times is a fairly common requirement, and as far as I’ve seen, Java doesn’t provide a built-in implementation out of the box. This makes the problem interesting, especially when we want to avoid increasing the application’s memory footprint by holding multiple copies.

For example, imagine you need to process a file and also forward a copy for audit purposes. Libraries such as Apache Commons IO offer solutions using piped streams, and other approaches involve duplicating the underlying stream. However, these options usually require buffering or storing the data somewhere, which is not always practical.

A more lightweight solution is to leverage markable streams. By wrapping the original stream in a BufferedInputStream (or any stream that supports marking), we can take advantage of the following API methods:

public synchronized void mark(int readLimit) public synchronized void reset() throws IOException public boolean markSupported()
  • mark(int readLimit) records the current position in the stream.

  • Later, reset() allows us to return to that position.

  • If the stream supports marking (markSupported()), we can safely use this mechanism.

By setting the read limit to a very large value (e.g., Integer.MAX_VALUE), you can effectively “rewind” the stream back to the beginning after consumption. This idea is well discussed in the following StackOverflow thread: How to cache InputStream for multiple use.

In my case, I kept the intuitive class name from that discussion but extended it slightly:

  • Added a method to explicitly close the decorated stream.

  • Ensured that if the provided InputStream does not support marking, it is automatically wrapped in a markable one (such as BufferedInputStream).


No comments:

Post a Comment