如何在最短的时间内在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秒的时间内完成.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


应用场景 C端用户提交工单、工单创建完成之后、会发布一条工单创建完成的消息事件(异步消息)、MQ消费者收到消息之后、会通知各处理器处理该消息、各处理器处理完后都会发布一条将该工单写入搜索引擎的消息、最终该工单出现在搜索引擎、被工单处理人检索和处理。 事故异常体现 1、异常体现 从工单的流转记录发现、
线程类,设置有一个公共资源 package cn.org.chris.concurrent; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Descrip
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)
在Java中找到正数和负数数组元素的数量
Java 9中JShell中的不同启动脚本是什么?
使用Java的位填充错误检测技术
java中string是什么
如何使用Java中的JSON-lib API将Map转换为JSON对象?
Java菜单驱动程序以检查数字类型
使用Junit的Maven项目 - 检查银行账号
JAVA编程基础
在Java中使用throw、catch和instanceof来处理异常
在Java中,将数组分割为基于给定查询的子数组后,找到子数组的最大子数组和
如何在Java中从给定的字符串中删除HTML标签?
在PHP中,IntlChar getBlockCode()函数的翻译如下:
如何在Android中实现按下返回键再次退出的功能?
如何使用Java中的流式API解析JSON字符串?
Java中的模式类