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.
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(); } }
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); }
you can read the entire file in a byte[] (slurp mode) then passing it to a ByteArrayInputStream
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