PrintStream
was the original bridge to deal with encoding characters and other datatypes. If you look at the javadoc for java.io.OutputStream
you’ll see methods only for writing two distinct data types: byte
and int
.
In early versions of the JDK (1.0.x), when you wanted to write characters, you could do one of two things, write bytes to an output stream (which are assumed to be in the system default character set):
outputStream.write("foobar".getBytes());
or wrap another outputStream
in a PrintStream
:
PrintStream printStream = new PrintStream(outputStream);
printStream.write("foobar");
See the difference? PrintStream
is handling the character conversion to bytes, as well as encoding (the constructor call above uses the system default encoding, but you could pass it as a parameter). It also provides convenience methods for writing double
, boolean
, etc….
In fact System.out
and System.err
are defined as PrintStream
instances.
Along comes JDK 1.1, and they realize they need a better way to deal with pure character data, since PrintStream
still has the byte based methods for writing. So they introduced the Writer
abstract class to deal strictly with char
, String
and int
data.
PrintWriter
adds methods for other types like double
, boolean
, etc…
Nowadays PrintWriter
also has format()
/ printf()
methods for format printing, etc…
As a general rule, if you’re writing character data, use Writer
instances. If you’re writing binary (or mixed) data use OutputStream
instances.