views:

838

answers:

4

What is the difference between PrintStream and PrintWriter? They have much methods in common. I always mix up this classes because of that reason. And I think we can use them for exactly the same. But there has to be a difference. Otherwise there was only one class.

I first searched on StackOverflow, but not yet this question.

+10  A: 

This might sound flippant, but PrintStream prints to an OutputStream, and PrintWriter prints to a Writer. Ok, I doubt I'll get any points for stating the obvious. But there's more.

So, what is the difference between an OutputStream and a Writer? Both are streams, with the primary difference being a OutputStream is a stream of bytes, while, a Writer it a stream of characters.

If an OutputStream deals with bytes, what about PrintStream.print(String)? It converts chars to bytes using the default platform encoding. Using the default encoding is generally a bad thing since it can lead to bugs when moving from one platform to another, especially if you are generating the file on one platform and consuming it on another.

With a Writer, you typically specify the encoding to use, avoiding any platform dependencies.

Why bother having a PrintStream in the JDK, since the primary intent is to write characters, and not bytes? PrintStream predates JDK 1.1 when Reader/Writer character streams were introduced. I imagine Sun would have deprecated PrintStream if only for the fact it is so widely used. (After all, you wouldn't want each call to System.out to generate a deprecated api wwarning! Also, changing the type from PrintStream to PrintWriter on the standard output streams would have broken existing applets applications.)

mdma
This is what I thought as well - but it's not true. Even PrintStream maintains a Writer under the hood - if you pass it an OutputStream, it wraps it.
Jon Skeet
@Jon - internally, there is a Writer, but it writes to an OutputStream, so the net effect is that a PrintStream writes to an OutputStream - char to byte conversion happens, and uses the default platform encoding. There is no such requirement for char->byte conversion in a PrintWriter, you can stay with characters all the way.
mdma
"The default charset is determined during virtual-machine startup andtypically depends upon the locale and charset of the underlyingoperating system.", also Locale changes the default charset on some platforms.
Pindatjuh
@mdma: I'd missed the fact that you can't pass a Writer to a PrintStream construtor...
Jon Skeet
+1  A: 

Writers like PrintWriter are for text output, streams are for binary output. The writers handle character set stuff for you. Streams don't because it's assumed that you don't want that sort of conversion, which would mess up your binary data, and would be using a writer if you did.

sblundy
Except PrintStream, because that one takes an encoding so it can handle a bit more than a standard OutputStream.
Simon Groenewolt
+1  A: 

You can write raw bytes to a Stream and not to a Writer. The PrintWriter javadoc lists the other differences (most importantly, being able to set an encoding on a stream so it can interpret the raw bytes I'd say).

Simon Groenewolt
+4  A: 

With the PrintStream you're sticked to platform's default encoding.

PrintStream stream = new PrintStream(output);

With the PrintWriter you can however pass an OutputStreamWriter with a specific encoding.

PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"));

The advantage is, well, that you can control the character encoding the characters should be written in so that they won't eventually end up as mojibake.

BalusC
+1 for teaching me a new word, mojibake :)
Jonik