如何缓存 InputStream 以供多次使用 [英] How to Cache InputStream for Multiple Use

查看:29
本文介绍了如何缓存 InputStream 以供多次使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文件的 InputStream,我使用 apache poi 组件来读取它,如下所示:

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

POIFSFileSystem fileSystem = new POIFSFileSystem(inputStream);

问题是我需要多次使用同一个流,POIFSFileSystem 在使用后关闭流.

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

缓存来自输入流的数据,然后将更多输入流提供给不同的 POIFSFileSystem 的最佳方法是什么?

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

编辑 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 ?

编辑 2:

很抱歉重新打开这个问题,但在桌面和 Web 应用程序中工作时,条件有些不同.首先,我从 org.apache.commons.fileupload.FileItem 在我的 tomcat web 应用程序中获得的 InputStream 不支持标记,因此无法重置.

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.

其次,我希望能够将文件保存在内存中,以便在处理文件时更快地访问并减少 io 问题.

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

推荐答案

你可以装饰传递给 POIFSFileSystem 的 InputStream 使用一个版本,当调用 close() 时它响应 reset():

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);
}

编辑 2

您可以在 byte[](slurp 模式)中读取整个文件,然后将其传递给 ByteArrayInputStream

EDIT 2

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

这篇关于如何缓存 InputStream 以供多次使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆