System.out关闭了吗?我可以重新打开吗?

时间:2012-01-20 12:13:21

标签: java io

我正在帮朋友写一些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()

有没有更好的方法来编写这样的辅助函数?

7 个答案:

答案 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的建议。

通常,流应该由打开/创建它们的一方关闭。

在您的方法中,只需刷新流即可。当它不再需要时,将其关闭。