0

我正在实现的 API 处理包含分层结构化数据的 InputStreams,即嵌套块,包括叶块中的许多图像。(如果你必须知道,我正在解析的是CBEFF数据。)每个数据块都以包含有关该块的一些元数据的标题作为前缀。

1st level 1 header
    1st level 2 header
    1st level 2 data block
    2nd level 2 header
    2nd level 2 data block
2nd level 1 header
    3rd level 2 header
    3rd level 2 data block

原始的 InputStream 是我的 API 类的构造函数的参数,并沿层次结构向下传递。目前,我正在 API 类的构造函数中将图像读入字节数组,因此每个构造函数在读取该类负责的完整数据时阻塞,稍后当客户端调用该 API 类的相关 getter 方法时,他们将获得从内存提供的图像数据。我宁愿以某种惰性 InputStreams 的形式向我的 API 的客户端提供包含的图像,这样图像字节只能从原始 InputStream 中读取,因为客户端读取了由吸气剂。例如,这使得进行渐进式渲染成为可能,这很有用,因为原始 InputStream 很慢。

有没有一种优雅的方法可以用 InputStreams 解决这个问题?

4

1 回答 1

1

InputStream不适合随机访问。因此,在大多数情况下,读取其中的部分内容是行不通的,即使您可以使用和的组合对某些输入流实现类似的效果。但并非所有流都支持,并且跳过字节通常与读取字节一样昂贵。resetskipreset

所以我建议你尝试一些替代方法。要么将整个流缓冲到某个随机访问缓冲区,例如临时文件,这仍然意味着首先从流中读取所有字节。或者您找到一种随机访问原始来源的方法。您没有指定要处理的源类型,但例如对于 HTTP 连接,您可以使用range request下载部件。类似的解决方案可能适用于其他来源。

无论您如何实现随机访问(并且看到您的评论,您可能会使用InputStreamwith resetand来实现skip),您都可以创建自己的类来表示该流的一部分。InputStream您可以通过子类化让该类本身成为一个实例FilterInputStream

cLass SubStream extends FilterInputStream {
    private long offset;
    public SubStream(long offset, InputStream parent) {
        super(parent);
        this.offset = offset;
    }
    public SubStream(InputStream parent) {
        this(0, parent);
    }
    @Override public void reset() throws IOException {
        in.reset();
        in.skip(offset);
    }
    public SubStream subStream(long offset) {
        return new FilterInputStream(this.offset + offset, in);
    }
    public Object syncObject() {
        return in;
    }
}

您必须确保reset首先调用这些流之一的任何操作。如果您需要强制执行适当的流结束处理,则必须覆盖大多数read实现。如果并发访问可能是可能的,那么您将需要同步底层流上的操作。所以使用这个类的代码可能看起来像这样:

     synchronized(part.syncObject()) {
         part.reset();
         return read(part);
     }
于 2012-08-13T09:17:44.173 回答