gpt4 book ai didi

java - 如何重新创建仅修改文件名的链接 OutputStream

转载 作者:行者123 更新时间:2023-12-01 10:35:34 24 4
gpt4 key购买 nike

我有一个OutputStream,可以将其初始化为OutputStreams 链。可以有任何级别的链接。唯一可以保证的是链的末尾是一个 FileOutputStream。

我需要使用 FileOutputStream 中修改后的文件名重新创建此链接的​​输出流。如果 out 变量(存储底层链式输出流)可访问,这是可能的;如下图所示。

public OutputStream recreateChainedOutputStream(OutputStream os) throws IOException {
if(os instanceof FileOutputStream) {
return new FileOutputStream("somemodified.filename");
} else if (os instanceof FilterOutputStream) {
return recreateChainedOutputStream(os.out);
}
}

还有其他方法可以达到同样的效果吗?

最佳答案

您可以使用反射来访问 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...
}
}

虽然这在您当前的应用程序中可能没问题,但在生产环境中这是一个很大的禁忌,因为您的应用程序可能会收到大量不同类型的 OutputStream。

更好的解决方法是 Function<String, OutputStream>作为一个工厂来创建 OutputStream s 代表指定的文件。这样外部 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 缓冲区。

关于java - 如何重新创建仅修改文件名的链接 OutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34764753/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com