Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java file input with rewind()/reset() capability

Tags:

java

io

stream

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(). :-(

like image 962
Jason S Avatar asked Jul 07 '09 20:07

Jason S


2 Answers

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);     } } 
like image 133
ykaganovich Avatar answered Sep 22 '22 20:09

ykaganovich


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.

like image 40
erickson Avatar answered Sep 23 '22 20:09

erickson