Java: Difference between PrintStream and PrintWriter
Asked Answered
H

6

134

What is the difference between PrintStream and PrintWriter? They have many methods in common due to which I often mix these two classes up. Moreover, I think we can use them for exactly the same things. But there has to be a difference, otherwise, there would have been only one class.

I have searched the archives, but couldn't find this question.

Haifa answered 12/5, 2010 at 19:14 Comment(2)
+1 Good question, I also mix up these two classes, and the API doc doesn't help much either.Bullis
Another difference is how autoflush works. For a writer the presence of a \n character in the output triggers flush(). But in a byte stream (PrintStream) there is only bytes. autoflush then works as described in Javadoc, based on: "platform's own notion of line separator rather than the newline character".Isiah
R
136

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 is 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 warning! Also, changing the type from PrintStream to PrintWriter on the standard output streams would have broken existing applications.)

Rubble answered 12/5, 2010 at 19:18 Comment(9)
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.Mapes
@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.Rubble
"The default charset is determined during virtual-machine startup and typically depends upon the locale and charset of the underlying operating system.", also Locale changes the default charset on some platforms.Punctilious
@Rubble - so, if PrintStream translates characters to bytes using the local char-set, what is the point of having something like FileWriter? Is it not a character stream? If so, why does it not allow you to define a char-set? Wouldn't it prove expensive to have read in some characters using FileReader which would convert bytes from the local char-set to Java's Unicode representation, just to write them out using the default char-set again? Why wouldn't a FileInputStream be better?Gadgeteer
FileWriter is a convenience class - it writes characters to a file using the default platform encoding. It's quite restrictive (e.g. can't specify encoding), and you could ask what's the point - and there isn't much other than convenience if you want to write strings to a file without caring about the encoding. It's not the same as PrintStream - this writes characters as bytes to an arbitrary byte stream. FileInputStream doesn't give you access to characters, just bytes, so if you need character data, then you'll need to convert somewhere. You could cast bytes to chars, fast but risky!Rubble
Since Java 1.5, PrintStream has not been limited to using the platform default encoding; there are constructors that accepts a charset name. Thus the distinctions between PrintStream and PrintWriter are that a PrintWriter cannot write raw bytes and the two classes wrap different types of destinations.Passible
It might be worth you also noting a significant difference in their behaviour, whilst they effectively share an interface PrintStream's print() methods are convenience functions which call write(), as such they trigger autoflush if enabled. PrintWriter on the other hand will not autoflush after a call to print(). I've been demonstrating some beginners Java today and this was catching some students out who weren't familiar with the need to manually flush. Otherwise your answer is great.Diviner
@Diviner PrintWriter has no difference in this aspect of auto flush, coz both PrintStream and PrintWriter have ability to do auto flush on every print()/write() call.Peres
@Peres You're correct, perhaps I should have clarified I was referring to default behaviour, as they were using a printwriter wrapped by some library.Diviner
P
22

Since JDK 1.4 it's possible to specify the character encoding for a PrintStream. Thus, the differences between PrintStream and PrintWriter are only about auto flushing behavior and that a PrintStream cannot wrap a Writer.

Penhall answered 23/1, 2011 at 20:22 Comment(0)
A
4

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.

Authority answered 12/5, 2010 at 19:20 Comment(3)
Except PrintStream, because that one takes an encoding so it can handle a bit more than a standard OutputStream.Domenic
Sounds strange that System.out, which sole goal is to print strings, is actually a PrintStream.Isiah
"The writers handle character set stuff for you" -- only the Writers that deal with converting characters to bytes. Not all Writers do.Colorfast
H
3

from core java by Horstmann

Java veterans might wonder whatever happened to the PrintStream class and to System.out. In Java 1.0, the PrintStream class simply truncated all Unicode characters to ASCII characters by dropping the top byte. (At the time, Unicode was still a 16-bit encoding.) Clearly, that was not a clean or portable approach, and it was fixed with the introduction of readers and writers in Java 1.1. For compatibility with existing code, System.in, System.out, and System.err are still input/output streams, not readers and writers. But now the PrintStream class internally converts Unicode characters to the default host encoding in the same way the PrintWriter does. Objects of type PrintStream act exactly like print writers when you use the print and println methods, but unlike print writers they allow you to output raw bytes with the write(int) and write(byte[]) methods.

Hofuf answered 11/8, 2019 at 11:29 Comment(0)
D
2

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

Domenic answered 12/5, 2010 at 19:23 Comment(1)
With PrintStream one can specify encoding as wellColorfast
S
-3

Printwriter is an enhancement of printstream.

I.E. printstream for a specific purpose.

Secundines answered 9/12, 2016 at 22:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.