133

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.

Shubham Goyal
  • 1,254
  • 4
  • 19
  • 24
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • 3
    +1 Good question, I also mix up these two classes, and the API doc doesn't help much either. – helpermethod May 24 '10 at 13:02
  • 2
    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". – mins May 24 '14 at 23:08

6 Answers6

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

Stack Overflow
  • 1
  • 5
  • 23
  • 51
mdma
  • 56,943
  • 12
  • 94
  • 128
  • 3
    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 May 12 '10 at 19:21
  • 4
    @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 May 12 '10 at 19:29
  • "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. – Pindatjuh May 12 '10 at 19:39
  • @mdma - 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? – wulfgarpro Aug 09 '11 at 23:11
  • `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! – mdma Aug 10 '11 at 10:31
  • 9
    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. – Ted Hopp May 09 '13 at 03:47
  • 2
    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. – Robadob Oct 06 '15 at 16:45
  • @Robadob `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. – ieXcept May 04 '16 at 23:39
  • 1
    @ieXcept You're correct, perhaps I should have clarified I was referring to default behaviour, as they were using a `printwriter` wrapped by some library. – Robadob May 05 '16 at 12:51
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.

Renan Mozone
  • 539
  • 5
  • 12
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.

sblundy
  • 60,628
  • 22
  • 121
  • 123
  • 1
    Except PrintStream, because that one takes an encoding so it can handle a bit more than a standard OutputStream. – Simon Groenewolt May 12 '10 at 19:25
  • Sounds strange that System.out, which sole goal is to print strings, is actually a PrintStream. – mins May 24 '14 at 22:53
  • "The writers handle character set stuff for you" -- only the Writers that deal with converting characters to bytes. Not all Writers do. – Aivar Apr 07 '15 at 15:20
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.

nichijou
  • 484
  • 4
  • 12
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).

Simon Groenewolt
  • 10,607
  • 1
  • 36
  • 64
-3

Printwriter is an enhancement of printstream.

I.E. printstream for a specific purpose.

Spoo
  • 205
  • 1
  • 4