我正在实现的一个应用程序接口处理包含分层结构化数据的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的形式提供给我的InputStream的客户机,这样,由于客户机读取由getter传递的结果InputStream的字节,所以只从原始的API读取图像字节。例如,这使得进行渐进式渲染成为可能,这在原始InputStream很慢的情况下很有用。
有没有一种优雅的方法可以用InputStreams来解决这个问题呢?
发布于 2012-08-13 17:17:44
InputStream不适合随机访问。因此,即使您可以使用reset和skip的组合在某些输入流上实现类似的效果,但在大多数情况下,读取它的某些部分是不会起作用的。但并不是所有的流都支持reset,跳过字节通常和读取字节一样昂贵。
所以我建议你尝试一些替代的方法。要么将整个流缓冲到某个随机访问缓冲区中,比如临时文件,这仍然意味着首先要从流中读取所有字节。或者你找到了一种随机访问原始源的方法。您没有指定您正在处理的源的类型,但是例如,对于HTTP连接,您可以使用range request进行download parts。类似的解决方案可能适用于其他来源。
无论您如何实现随机访问(看到您的评论,您很可能会使用带有reset和skip的InputStream来实现),您都可以创建自己的类来表示该流的一部分。您可以通过将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);
}https://stackoverflow.com/questions/11925971
复制相似问题