System.out closed? Can I reopen it?

前端 未结 7 2244
逝去的感伤
逝去的感伤 2020-12-06 09:34

I was helping a friend to write some Java code, who doesn\'t know a lot about Java. So I wrote him some helper functions to easily get things done that are a little quirky i

相关标签:
7条回答
  • 2020-12-06 10:09

    If you want to try the output on JVM console, you'd better to get a Console instance with System.console(). And then get the PrintWriter with console.writer() method. After using the PrintWriter, you can close it. Based on the console description of JavaDoc,

    Invoking close() on the objects returned by the reader() and the writer() will not close the underlying stream of those objects.

    You can do this again and again. No need to worrying about reopen the stream.

    0 讨论(0)
  • 2020-12-06 10:13

    You can check if the out input being passed is System.out and selectively decide not to close.

    The flush() call is necessary. Note that I am doing == check since the references will be identical if you were to invoke this write method with a System.out argument.

    public void write(String txt, OutputStream out) {
        PrintWriter printer = new PrintWriter(out);
        printer.print(txt);
        printer.flush();
    
        if(out != System.out) {
            printer.close();
        }
    }
    

    But honestly, I would keep a different method for closing or call this method writeAndClose in order to avoid the confusion.

    If you want to maintain abstraction (as hinted by @Urs), do the below. But I don't see the point of this rather over-engineering

    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 讨论(0)
  • 2020-12-06 10:18

    Do what Stas Kurilin suggests.

    In general, streams should be closed by the party that opened/created them.

    In your method, just flush the stream. Close it wherever it was opened when it is no longer needed.

    0 讨论(0)
  • 2020-12-06 10:21

    The general contract for OutputStream's close:

    public void close() throws IOException Closes this output stream and releases any system resources associated with this stream. The general contract of close is that it closes the output stream. A closed stream cannot perform output operations and cannot be reopened.

    PrintStream's

    public void close() Close the stream. This is done by flushing the stream and then closing the underlying output stream.

    The only advice I can give you is that you should not write asymmetrical code, that is, don't delegate the closing of resources your code has created to somewhere else.

    Even if in your case it might seemed sensible to close the wrapper stream, the fact is that you should not because you are closing a stream opened somewhere else.

    In short:

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

    Oh, and by the way, you may want to change the function name to print, rather than write.

    0 讨论(0)
  • 2020-12-06 10:22

    Like the others have said, a stream should be closed where it was opened. However, you could write a facade to protect a stream from getting closed like this:

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

    and use it like this:

    new StreamHelper().write("Hello Test", new UnclosableOutputStream(System.out));
    

    Might come in handy for test scenarios etc.

    0 讨论(0)
  • 2020-12-06 10:25

    Let's look at this from the caller's point of view.

    The caller has an OutputStream of some sort, and calls a method called write(). After the call completes, the caller discovers that the stream has been closed.

    In my view, your write() method simply should not call printer.close(). The latter closes the stream provided by the caller and is probably not what the caller expects.

    If you need to flush the stream, you could use flush().

    0 讨论(0)
提交回复
热议问题