Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Cache InputStream for Multiple Use

I have an InputStream of a file and i use apache poi components to read from it like this:

POIFSFileSystem fileSystem = new POIFSFileSystem(inputStream); 

The problem is that i need to use the same stream multiple times and the POIFSFileSystem closes the stream after use.

What is the best way to cache the data from the input stream and then serve more input streams to different POIFSFileSystem ?

EDIT 1:

By cache i meant store for later use, not as a way to speedup the application. Also is it better to just read up the input stream into an array or string and then create input streams for each use ?

EDIT 2:

Sorry to reopen the question, but the conditions are somewhat different when working inside desktop and web application. First of all, the InputStream i get from the org.apache.commons.fileupload.FileItem in my tomcat web app doesn't support markings thus cannot reset.

Second, I'd like to be able to keep the file in memory for faster acces and less io problems when dealing with files.

like image 353
Azder Avatar asked May 29 '09 08:05

Azder


1 Answers

you can decorate InputStream being passed to POIFSFileSystem with a version that when close() is called it respond with reset():

class ResetOnCloseInputStream extends InputStream {      private final InputStream decorated;      public ResetOnCloseInputStream(InputStream anInputStream) {         if (!anInputStream.markSupported()) {             throw new IllegalArgumentException("marking not supported");         }          anInputStream.mark( 1 << 24); // magic constant: BEWARE         decorated = anInputStream;     }      @Override     public void close() throws IOException {         decorated.reset();     }      @Override     public int read() throws IOException {         return decorated.read();     } } 

testcase

static void closeAfterInputStreamIsConsumed(InputStream is)         throws IOException {     int r;      while ((r = is.read()) != -1) {         System.out.println(r);     }      is.close();     System.out.println("=========");  }  public static void main(String[] args) throws IOException {     InputStream is = new ByteArrayInputStream("sample".getBytes());     ResetOnCloseInputStream decoratedIs = new ResetOnCloseInputStream(is);     closeAfterInputStreamIsConsumed(decoratedIs);     closeAfterInputStreamIsConsumed(decoratedIs);     closeAfterInputStreamIsConsumed(is); } 

EDIT 2

you can read the entire file in a byte[] (slurp mode) then passing it to a ByteArrayInputStream

like image 184
dfa Avatar answered Oct 07 '22 02:10

dfa