I need to write a function that takes in some kind of input stream thing (e.g. an InputStream or a FileChannel) in order to read a large file in two passes: once to precompute some capacities, and second to do the "real" work. I do not want the whole file loaded into memory at once (unless it is small).
Is there an appropriate Java class that provides this capability? FileInputStream itself does not support mark()/reset(). BufferedInputStream does, I think, but I'm not clear whether it has to store the whole file to do this.
C is so simple, you just use fseek(), ftell(), and rewind(). :-(
I think the answers referencing a FileChannel are on the mark .
Here's a sample implementation of an input stream that encapsulates this functionality. It uses delegation, so it's not a true FileInputStream, but it is an InputStream, which is usually sufficient. One could similarly extend FileInputStream if that's a requirement.
Not tested, use at your own risk :)
public class MarkableFileInputStream extends FilterInputStream { private FileChannel myFileChannel; private long mark = -1; public MarkableFileInputStream(FileInputStream fis) { super(fis); myFileChannel = fis.getChannel(); } @Override public boolean markSupported() { return true; } @Override public synchronized void mark(int readlimit) { try { mark = myFileChannel.position(); } catch (IOException ex) { mark = -1; } } @Override public synchronized void reset() throws IOException { if (mark == -1) { throw new IOException("not marked"); } myFileChannel.position(mark); } }
BufferedInputStream
supports mark
by buffering the content in memory. It is best reserved for relatively small look-aheads of a predictable size.
Instead, RandomAccessFile
can be used directly, or it could serve as the basis for a concrete InputStream
, extended with a rewind()
method.
Alternatively, a new FileInputStream
can be opened for each pass.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With