【问题标题】:Lazy access to InputStream by offering InputStream getter通过提供 InputStream getter 对 InputStream 进行延迟访问
【发布时间】:2012-08-12 21:19:58
【问题描述】:

我正在实现的 API 处理包含分层结构化数据的 InputStream,即嵌套块,包括叶块中的许多图像。 (如果你必须知道,我正在解析的是 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 解决这个问题的优雅方法?

【问题讨论】:

  • 呃,把你所有的读图代码都删掉了吗?
  • @EJP,是的,如果只有一个图像并且图像数据是 InputStream 中的最后一个元素,那么这将起作用。我有多个图像,图像 n_+1 的标题跟随图像 _n 的数据。我会澄清这个问题。

标签: java io inputstream


【解决方案1】:

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

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

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

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);
     }

【讨论】:

  • 来源是智能卡读卡器中的智能卡(因此,连接速度非常慢,我们这里只讨论几kbps,因此需要支持渐进式渲染)。支持标记和重置,跳过很便宜。
猜你喜欢
  • 2013-10-17
  • 1970-01-01
  • 2012-09-02
  • 2011-09-21
  • 2012-11-09
  • 2017-04-13
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
相关资源
最近更新 更多