2012-01-20 82 views
18

我正在帮助一位朋友编写一些Java代码,他们对Java没有多少了解。所以我给他写了一些辅助功能,以便轻松完成他眼中有点古怪的事情。其中之一是一个函数,它将字符串写入OutputStream。看看:System.out已关闭?我可以重新打开它吗?

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()不写什么壳了。所以我认为可能printer.close()也自动关闭了System.out,我想知道如何重新激活它,以便我可以在此功能再次完成后使用它。

我的假设是否正确? (我怎么能在这里没有问到这个问题呢?)

如何在write()函数调用后继续使用System.out

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

+3

我相信,你可以使用'flush'而不是'close()'。 –

+1

您可以使用'write'方法'static'来避免丑陋的'(新的StreamHelper())。write(...)'调用。 – adarshr

+2

@Stas Kurilin:我试过了,它工作。 – erikbwork

回答

19

OutputStream的接近常规协定:

公共无效的close() 抛出IOException关闭此输出流并释放与此流相关的所有系统资源。关闭的一般合约 是关闭输出流。封闭流不能执行输出操作,并且不能重新打开

PrintStream

公共无效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

+0

我认为它包含一个答案,也是解决问题的办法。感谢大家的帮助! – erikbwork

3

System.out是一个PrintStream,因此上面提供的代码与直接调用System.out.print几乎没有任何优势。它不再写的原因是,close确实接近System.out

如果这是用于日志记录,请为您的朋友学习log4j或帮助他学习它。 Log4j可以同时很好地处理需要写入文件流,标准输出等情况。

+2

不完全。它具有抽象的优点,因为您可以使用System.out以及任何其他流。 –

+2

除非他有一个实际需要这种抽象的用例,例如日志记录,否则就没有意义。 –

3

您可以检查输入的out是否为System.out并有选择性地决定不关闭。

flush()电话是必要的。请注意,我正在执行==检查,因为如果您要用System.out参数调用此write方法,则引用将相同。

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(); 
} 
+0

抽象创建原始解决方案。 –

2

让我们来看看这个从查看来电者的观点。

调用者有某种OutputStream,并调用一个名为write()的方法。呼叫完成后,呼叫者发现该流已关闭。

在我看来,您的write()方法根本不应该调用printer.close()。后者关闭了调用者提供的流,可能不是调用者期望的。

如果您需要刷新流,可以使用flush()

2

做什么斯塔斯Kurilin建议。

一般来说,流应由开放/创建它们的一方关闭。

在你的方法中,只需刷新流。不再需要时将其关闭。

+0

+1用于宣传我的名字) –

9

像其他人所说的那样,一条小溪应该在它被打开的地方关闭。然而,你可以写一个门面,以保护流从得到关闭这样的:

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)); 

可能会派上用场的测试场景等

相关问题