我正在实现的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方法时,它们将获得从内存中提供的图像数据。我宁愿以某种懒惰的InputStream形式向我的API的客户端提供包含的图像,这样只有客户端读取由此产生的结果InputStream的字节,才能从原始的InputStream中读取图像字节。吸气。例如,这使得可以进行渐进式渲染,这在原始InputStream很慢时非常有用。
使用InputStreams有一种优雅的方法来解决这个问题吗?
答案 0 :(得分:1)
InputStream
不适合随机访问。因此,在大多数情况下,阅读部分内容并不适用,即使您可以使用reset
和skip
的组合对某些输入流实现类似的效果。但并非所有流都支持reset
,跳过字节通常与读取字节一样昂贵。
所以我建议你尝试一些替代方法。您可以将整个流缓冲到某个随机访问缓冲区,就像临时文件一样,这仍然意味着首先从流中读取所有字节。或者您找到了一种随机访问原始源的方法。您没有指定您正在处理的来源,例如对于HTTP连接,您可以使用download parts range request。类似的解决方案可能适用于其他来源。
无论您如何实施随机访问(并看到您的评论,您可能会使用InputStream
reset
和skip
),您可以创建自己的类表示该流的一部分。您可以通过继承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);
}