我正在帮朋友写一些Java代码,他们对Java知之甚少。所以我给他写了一些辅助函数来轻松完成他眼中有点古怪的事情。其中一个是函数,它将一个String写入OutputStream
。看看:
public void write(String txt, OutputStream out) {
PrintWriter printer = new PrintWriter(out);
printer.print(txt);
printer.close();
}
现在,您可以通过不同的方式轻松地使用它来编写您想要的任何地方。例如,你可以这样做:
(new StreamHelper()).write("Hello Test", System.out);
这样做我发现之后System.out.println()
不再向shell写任何内容了。所以我认为printer.close()
可能会自动关闭System.out
,我想知道如何重新激活它,我可以在此功能再次完成后使用它。
我的假设是否正确? (如果不问这里我怎么能找到?)
如何在致电System.out
功能后继续使用write()
?
有没有更好的方法来编写这样的辅助函数?
答案 0 :(得分:20)
OutputStream
关闭的一般合约:
public void close() throws IOException关闭此输出流并释放与此流关联的所有系统资源。一般合同 close是关闭输出流。封闭的流不能 执行输出操作,无法重新打开。
PrintStream
的
public void close()关闭流。这是通过冲洗来完成的 流然后关闭基础输出流。
我能给你的唯一建议是你不应该写asymmetrical code,也就是说,不要将代码创建的资源关闭委托给其他地方。
即使在你的情况下,关闭包装器流似乎也是合理的,事实是你不应该因为你正在关闭在其他地方打开的流。
简而言之:
public void write(String txt, OutputStream out) {
PrintWriter printer = new PrintWriter(out);
printer.print(txt);
printer.flush();
//it is very unpolite to close someone else's streams!
//printer.close();
}
哦,顺便说一下,您可能希望将函数名称更改为print
,而不是write
。
答案 1 :(得分:10)
与其他人所说的一样,流应该在打开的地方关闭。但是,您可以编写一个外观来保护流不会像这样关闭:
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class UnclosableOutputStream extends FilterOutputStream {
public UnclosableOutputStream(OutputStream out) {
super(out);
}
@Override
public void close() throws IOException {
out.flush();
}
}
并像这样使用它:
new StreamHelper().write("Hello Test", new UnclosableOutputStream(System.out));
对于测试场景等可能会派上用场。
答案 2 :(得分:3)
System.out
是一个PrintStream,因此上面提供的代码与直接调用System.out.print
相比没有任何优势。它不再写作的原因是close
实际上关闭了System.out
。
如果这是用于记录,请为您的朋友学习log4j或帮助他学习它。 Log4j可以处理需要同时写入文件流,标准输出等的情况。
答案 3 :(得分:3)
您可以检查传递的out
输入是否为System.out
,并有选择地决定不关闭。
flush()
电话是必要的。请注意,我正在进行==
检查,因为如果您使用write
参数调用此System.out
方法,则引用将是相同的。
public void write(String txt, OutputStream out) {
PrintWriter printer = new PrintWriter(out);
printer.print(txt);
printer.flush();
if(out != System.out) {
printer.close();
}
}
但老实说,我会保留一种不同的方法来关闭或调用此方法writeAndClose
以避免混淆。
如果你想保持抽象(如@Urs暗示的那样),请执行以下操作。但我没有看到这个过度工程
的重点public void write(String txt, OutputStream out) {
PrintWriter printer = new PrintWriter(out);
printer.print(txt);
printer.flush();
}
public void close(OutputStream out) {
out.close();
}
答案 4 :(得分:3)
如果您想在JVM控制台上尝试输出,最好使用System.console()
获取一个Console实例。然后使用PrintWriter
方法获得console.writer()
。使用PrintWriter
之后,您可以将其关闭。根据JavaDoc的控制台说明,
在
close()
返回的对象上调用reader()
writer()
不会关闭这些对象的基础流。
您可以一次又一次地执行此操作。无需担心重新打开流。
答案 5 :(得分:2)
让我们从来电者的角度来看这个。
调用者具有某种OutputStream
,并调用名为write()
的方法。呼叫完成后,呼叫者发现该流已关闭。
在我看来,您的write()
方法不应该致电printer.close()
。后者关闭调用者提供的流,可能不是调用者所期望的。
如果您需要刷新流,可以使用flush()
。
答案 6 :(得分:2)
做Stas Kurilin的建议。
通常,流应该由打开/创建它们的一方关闭。
在您的方法中,只需刷新流即可。当它不再需要时,将其关闭。