在项目中遇到一个FileBackedOutputStream的坑,在此记录一下。
因为某些原因,需要实现一个ResettableInputStream,大家都知道,JDK中,ByteArrayInputStream是可以mark、reset的,但是代价就是将所有数据都load进内存,在数据量较大时,这是无法接受的。因为我们需要的是任意的在流中穿梭的能力,这时候,可以借助磁盘来完成这一功能。索性,Guava中提供了一个类,FileBackedOutputStream,将数据写入其中之后,如果数据超过一定限度,它就会将数据写入磁盘。
FileBackedOutputStream的构造函数如下所示,里面提供了一个叫supplier的类,这个类作为OutputStream的出口。这里应该注意一下,如果resetOnFinalize这一个参数如果设为true的话,supplier会重写finalize方法,里面调用reset操作。这也是本篇文章出现的原因。
public FileBackedOutputStream(int fileThreshold, boolean resetOnFinalize) {
this.fileThreshold = fileThreshold;
this.resetOnFinalize = resetOnFinalize;
memory = new MemoryOutput();
out = memory;
if (resetOnFinalize) {
supplier = new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return openStream();
}
@Override protected void finalize() {
try {
reset();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
};
} else {
supplier = new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return openStream();
}
};
}
}
public InputSupplier<InputStream> getSupplier() {
return supplier;
}