gpt4 book ai didi

java - 如何在最短时间内用 Java 克隆输入流

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:53:26 25 4
gpt4 key购买 nike

有人能告诉我如何克隆一个输入流,并尽可能少地花费创建时间吗?我需要多次克隆输入流以使用多种方法来处理 IS。我已经尝试了三种方法,但由于某种原因,一切都不奏效。

方法一:感谢 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,0,read);
byte[] ba = bos.toByteArray();

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

方法#2:我还尝试使用 BufferedInputStream 克隆 IS。这很快(最慢的创建时间 == 1 毫秒。最快的 == 0 毫秒)。然而,在我发送 is1 进行处理后,处理 is2 和 is3 的方法抛出一个错误,说没有什么要处理的,几乎就像下面的所有 3 个变量都引用了相同的 IS。

    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)这个程序在虚拟机上运行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, 0, 1);
return b[0];
}

@Override
public int read(byte[] bytes) throws IOException {
return read(bytes, 0, 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, offset, read);
return read;
}
} else {
int read = Math.min(length, buffer.remaining());

if (read <= 0) {
buffer.flip();
return -1;
} else {
buffer.get(bytes, offset, 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 - 如何在最短时间内用 Java 克隆输入流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13301076/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com