您可以使用反射来访问FilterOutputStream
的os.out场,这可是有一些缺点:
- 如果对方的OutputStream也是一种RolloverOutputStream的,你可以有一个很难重建它,
- 如果其他的OutputStream具有自定义设置,如Gzip压缩参数,你可以不可靠的阅读
- 如果有
一个快速和肮脏的实施recreateChainedOutputStream(
可能是:
private final static Field out;
{
try {
out = FilterInputStream.class.getField("out");
out.setAccessible(true);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public OutputStream recreateChainedOutputStream(OutputStream out) throws IOException {
if (out instanceof FilterOutputStream) {
Class<?> c = ou.getClass();
COnstructor<?> con = c.getConstructor(OutputStream.class);
return con.invoke(this.out.get(out));
} else {
// Other output streams...
}
}
虽然这可能是当前应用程序确定,这是一个很大的禁忌在生产世界,因为大量不同种类的OutputStreams您的应用程序的可能会收到。
解决问题的更好方法是一种Function<String, OutputStream>
,它可以作为工厂为指定文件创建OutputStream
。通过这种方式,外部api可以控制OutputStream
,而您的api可以处理多个文件名。这方面的一个例子是:
public class MyApi {
private final Function<String, OutputStream> fileProvider;
private OutputStream current;
public MyApi (Function<String, OutputStream> fileProvider, String defaultFile) {
this.fileProvider = fileProvider;
selectNewOutputFile(defaultFile);
}
public void selectNewOutputFile(String name) {
OutputStream current = this.current;
this.current = fileProvider.apply(name);
if(current != null) current.close();
}
}
这然后可以在其它应用中被用作:
MyApi api = new MyApi(name->new FileOutputStream(name));
对于简单FileOutputStream
S,或可以用作:
MyApi api = new MyApi(name->
new GZIPOutputStream(
new CipherOutputStream(
new CheckedOutputStream(
new FileOutputStream(name),
new CRC32()),
chipper),
1024,
true)
);
对于文件流存储校验和使用new CRC32()
,使用chipper
切片,gzip根据具有同步写入模式的1024缓冲区。
看起来像是X-Y问题。为什么这需要? – Ferrybig
我想编写一个RolloverOutputStream,它可以自己滚动文件,其中消费者类应该能够通过传入基础OutputStream(可以是FileOutputStream上的GZipOutputStream或普通的FileOutputStream或更多的组合)以及阈值应该在哪些文件上滚动。消费应用程序应该能够无限期地继续写入,而RolloverOutputStream在数据大小超过阈值时处理翻转。 – rajeshnair
如果你想创建一个'RolloverOutputStream',创建'OutputStream'的自定义实现将会更容易,该实现有'setOutputStream()'方法来选择它的目标。您当前的解决方案依赖于输出流是链的顶端的事实,在所有应用中可能并非总是如此。 – Ferrybig