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
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 thereader()
and thewriter()
will not close the underlying stream of those objects.
You can do this again and again. No need to worrying about reopen the stream.
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();
}
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.
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
.
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.
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()
.