Java has a nice IO subsystem. In particular, it has been designed
such that input streams can optionally support a feature where a
programmer can mark a position in the stream and at a later
stage return to that point to read the data again. Programmers can check
for this support by calling InputStream.markSupported().
Unfortunately I’ve had the need for this support, but I haven’t managed
to find a stream which supports this. Not even
ByteArrayInputStream sees to support it. Fortunately it’s
fairly trivial to wrap an InputStream in another class which
will add this support. Here is my quick adaptor, which seems to work
for most cases.
import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; public class MarkableInputStream extends InputStream { private InputStream inputstream; private int maxpos = 0; private int curpos = 0; private int mark = 0; private ArrayList<Integer> buffer = new ArrayList<Integer>(); public MarkableInputStream(InputStream is) { inputstream = is; } @Override public int read() throws IOException { int data; if(curpos == maxpos) { data = inputstream.read(); buffer.add(data); maxpos++;curpos++; } else { data = buffer.get(curpos++); } return data; } @Override public synchronized void mark(int readlimit) { mark = curpos; } @Override public boolean markSupported() { return true; } @Override public synchronized void reset() throws IOException { curpos = mark; } }
You can use it like:
if (!istream.markSupported()) { istream = new MarkableInputStream(istream); }
This could probably be improved on, most notably by not using an
ArrayList. I’m not sure what performance penalty that adds. It
should be possible to use a normal array as the readlimit
parameter to mark() says how many bytes the stream should
record before throwing old data away in favour of new input. The class
above will record all data from the start of the stream, so could result
in a significant amount of memory usage. Hope you find it useful.
on said:
I think you just reimplemented BufferedInputStream:
A BufferedInputStream adds functionality to another input stream-namely, the ability to buffer the input and to support the mark and reset methods.