如何在最短的时间内在java中克隆输入流

前端之家收集整理的这篇文章主要介绍了如何在最短的时间内在java中克隆输入流前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有人可以告诉我如何克隆输入流,尽可能少的创建时间?我需要多次克隆输入流以便多种方法来处理IS.我尝试了三种方法,因为某种原因,事情不起作用.

方法#1:
感谢stackoverflow社区,我发现以下链接很有帮助,并将代码片段合并到我的程序中.

How to clone an InputStream?

但是,使用此代码最多可能需要一分钟(对于10MB文件)来创建克隆的输入流,并且我的程序需要尽可能快.

int read = 0;
    byte[] bytes = new byte[1024*1024*2];

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    while ((read = is.read(bytes)) != -1)
        bos.write(bytes,read);
    byte[] ba = bos.toByteArray();

    InputStream is1 = new ByteArrayInputStream(ba);
    InputStream is2 = new ByteArrayInputStream(ba);
    InputStream is3 = new ByteArrayInputStream(ba);

方法#2:
我也尝试使用BufferedInputStream来克隆IS.这很快(创建时间最慢== 1ms.最快== 0ms).但是,在我发送is1进行处理之后,方法处理is2和is3引发了一个错误,说没有什么可以处理,几乎就像下面引用相同的IS的所有3个变量一样.

is = getFileFromBucket(path,filename);
    ...
    ...
    InputStream is1 = new BufferedInputStream(is);
    InputStream is2 = new BufferedInputStream(is);
    InputStream is3 = new BufferedInputStream(is);

方法#3:
我认为编译器对我说谎.我在上面两个例子中检查了is1的markSupported().它返回true,所以我以为我可以跑了

is1.mark() 
    is1.reset()

要不就

is1.reset();

在将IS传递给我各自的方法之前.在上面的两个例子中,我收到一个错误,说它是无效标记.

我现在没有想法,所以提前感谢你能给我的任何帮助.

附:从我收到的人们的评论中,我需要澄清一些与我的情况有关的事情:
1)该程序在VM上运行
2)输入流正从另一种方法传递给我.我不是从本地文件中读取的
3)输入流的大小未知

解决方法

how to clone an inputstream,taking as little creation time as possible? I need to clone an inputstream multiple times for multiple methods to process the IS

您可以创建某种自定义的ReusableInputStream类,其中您在第一次完整读取时立即写入内部ByteArrayOutputStream,然后在读取最后一个字节时将其包装在ByteBuffer中,最后在后续完整读取时重用相同的ByteBuffer当达到限制时会自动翻转.这样可以避免您在第一次尝试时完全阅读.

这是一个基本的启动示例:

public class ReusableInputStream extends InputStream {

    private InputStream input;
    private ByteArrayOutputStream output;
    private ByteBuffer buffer;

    public ReusableInputStream(InputStream input) throws IOException {
        this.input = input;
        this.output = new ByteArrayOutputStream(input.available()); // Note: it's resizable anyway.
    }

    @Override
    public int read() throws IOException {
        byte[] b = new byte[1];
        read(b,1);
        return b[0];
    }

    @Override
    public int read(byte[] bytes) throws IOException {
        return read(bytes,bytes.length);
    }

    @Override
    public int read(byte[] bytes,int offset,int length) throws IOException {
        if (buffer == null) {
            int read = input.read(bytes,offset,length);

            if (read <= 0) {
                input.close();
                input = null;
                buffer = ByteBuffer.wrap(output.toByteArray());
                output = null;
                return -1;
            } else {
                output.write(bytes,read);
                return read;
            }
        } else {
            int read = Math.min(length,buffer.remaining());

            if (read <= 0) {
                buffer.flip();
                return -1;
            } else {
                buffer.get(bytes,read);
                return read;
            }
        }

    }

    // You might want to @Override flush(),close(),etc to delegate to input.
}

(请注意,实际作业是在int read(byte [],int,int)中执行而不是在int read()中执行,因此当调用者本身也使用byte []缓冲区进行流式处理时,预期会更快.

您可以按如下方式使用它:

InputStream input = new ReusableInputStream(getFileFromBucket(path,filename));
IoUtils.copy(input,new FileOutputStream("/copy1.ext"));
IoUtils.copy(input,new FileOutputStream("/copy2.ext"));
IoUtils.copy(input,new FileOutputStream("/copy3.ext"));

至于性能,每10MB 1分钟更可能是硬件问题,而不是软件问题.我的7200rpm笔记本电脑硬盘在不到1秒的时间内完成.

猜你在找的Java相关文章