【问题标题】:SequenceInputStream constructor only picks the first input stream and ignores restSequenceInputStream 构造函数只选择第一个输入流并忽略其余
【发布时间】:2015-07-06 22:30:25
【问题描述】:

我正在使用 SequenceInputStream 将多个流合并为一个流。我在JDK8上。以下是代码。

private InputStream mergeInputStreams(final Map<String, InputStream> fileAssets, final JSONObject json) throws Exception {

    final List<InputStream> listStreams = new ArrayList<InputStream>();

    listStreams.add(stringToStream(HEADER));
    addToList(json, listStreams);

    listStreams.add(stringToStream(HEADER_2));
    addToList(fileAssets.get(FILE_2), listStreams, true);

    listStreams.add(stringToStream(HEADER_3));
    addToList(fileAssets.get(FILE_3), listStreams, false);

    return new SequenceInputStream(Collections.enumeration(listStreams));
}

private void addToList(final InputStream inputStream, List<InputStream> listStreams, final boolean delimiter) throws Exception {
    final byte[] input = byteArrayFromStream(inputStream);
    listStreams.add(intToStream(input.length));
    listStreams.add(new ByteArrayInputStream(input));
    if (delimiter) {
        listStreams.add(stringToStream("\n"));
    }
}

private void addToList(final JSONObject json, final List<InputStream> listStreams) throws Exception {
    final String jsonString = json.toString();
    listStreams.add(intToStream(jsonString.length()));
    listStreams.add(stringToStream(jsonString));
}

我遇到的问题是,我总是从 SequenceInputStream 对象获取第一个流,即我只获取 HEADER 字符串。我尝试了几种选择,包括

new SequenceInputStream(listStreams.get(9), listStreams.get(9)); 

在上面的示例中,我尝试将相同的输入合并两次。但是,我仍然只得到第 9 个输入流一次。

我已经验证我确实在枚举中获得了多个流。

如果有人能帮助我了解这里发生了什么,那就太好了。

【问题讨论】:

    标签: java inputstream java-io filemerge


    【解决方案1】:

    以下是我们所拥有的:

    1. 从“n”个流中创建一个序列输入流对象“s”
    2. 使用外部库将“s”上传到 S3。 lib.uploadToS3(s)

    问题: 第三方库 uploadToS3(stream) 调用使用 stream.available() 来初始化缓冲区数组,并从流中填充并上传。

    看起来 SequenceInputStream.available() (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/io/SequenceInputStream.java) 从其迭代的当前流返回 available()。例如在 lib.uploadToS3() 的上下文中,它使用的是序列中第一个流中的 available()。

    我们修复了什么: 我们修复了库以使用 IOUtils.copy() 而不是编写依赖于 available() 的复制代码。

    【讨论】:

    • 干得好。我仍然觉得令人难以置信的是人们会使用 available() 来完成 Javadoc 告诉你不要使用它的事情。
    • 我会进一步指出,期望 available() 返回底层流的总和 available() imethods 是不合理的。如果第一个流有 M 个字节“可用”而没有阻塞,而另外 N 个字节可以通过阻塞读取,那么在没有阻塞的情况下可以从其他流中读取什么是完全不相关的,因为必须先读取 N 个字节。
    【解决方案2】:

    它将读取第一个流直到流结束,然后是第二个,依此类推。可能这不是你所期待的?这也意味着您不能两次提供相同的流,因为它在第一次使用时已经被完全读取。

    我看不出构造函数与它有什么关系。

    【讨论】:

    • 是的。我相信它正在这样做。我只是在尝试可用。看起来它逐个流返回可用流,即如果我们有 3 个流,第一次它将返回仅第一个流的可用()计数。看起来我的代码下游正在使用 InputReader 对象直接调用 available() 来获取这么多字节。这对我来说似乎是错误的。当我发现更多时,我会提供更新。
    • 它甚至没有义务这样做。如果您期望它返回所有流的总长度,那么这是一种滥用,Javadoc 中特别警告了这一点。 available().的正确用法很少,不要使用。
    • 我同意。我碰巧检查了正在使用它的下游库。让我建议对其进行修改,使其不使用 available()。谢谢。
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多