方法#1:
感谢stackoverflow社区,我发现以下链接很有帮助,并将代码片段合并到我的程序中.
但是,使用此代码最多可能需要一分钟(对于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秒的时间内完成.