PrintWriter autoflush puzzling logic - java

public PrintWriter(OutputStream out, boolean autoFlush):
out - An output stream
autoFlush - A boolean; if true, the println, printf, or format methods
will flush the output buffer
public PrintStream(OutputStream out, boolean autoFlush):
out - The output stream to which values and objects will be printed
autoFlush - A boolean; if true, the output buffer will be flushed
whenever a byte array is written, one of the println methods is invoked,
or a newline character or byte ('\n') is written
What was the reason for changing autoflush logic between these classes?
Because they are always considered as identical except for encoding moments and "autoflush" without flushing on print() hardly corresponds to principle of least astonishment, silly bugs occur:
I created a PrintWriter with autoflush on; why isn't it autoflushing?

I think the answer lies in the history of Java. The trio InputStream, OutputStream and PrintStream in java.io date back to Java 1.0. That is before serious support for file encodings and character sets were built into the language.
To quote the Javadoc:
"A PrintStream adds functionality to
another output stream, namely the
ability to print representations of
various data values conveniently. Two
other features are provided as well.
Unlike other output streams, a
PrintStream never throws an
IOException; instead, exceptional
situations merely set an internal flag
that can be tested via the checkError
method..."
To summarize, it is a convenience for generating textual output, grafted on top of lower level IO.
In Java 1.1, Reader, Writer and PrintWriter were introduced. Those all support character sets. While InputStream and OutputStream still had a real uses (raw data processing), PrintStream became far less relevant, because printing by nature is about text.
The Javadoc for PrintWriter explicitly states:
Unlike the PrintStream class, if
automatic flushing is enabled it will
be done only when one of the println()
methods is invoked, rather than
whenever a newline character happens
to be output. The println() methods
use the platform's own notion of line
separator rather than the newline
character.
Put another way, PrintWriter should only be used through the print*(...) APIs, because writing newline characters etc should not be the caller's responsibility, the same way dealing with file encodings and character sets are not the caller's responsibility.
I would argue that PrintWriter should have been java.io.Printer instead, and not have extended Writer. I don't know whether they extended to mimic PrintStream, or because they were stuck on maintaining the pipe design idiom.

The reason it wasn't the same at start was probably just an accident. Now it's backwards compatibility.

Related

Java writing to File or System.out

I need to write characters to a file or to standard output. And I am curious if it could be done with one method.
Now I have something like this:
OutputStream out;
if(toConsole)
out = System.out;
else
out = new FileOutputStream(file);
write(out);
}
void write (OutputStream str){
....
str.write(string);
But it is a problem that I am using (in case when "str" is System.out) write instead print?
(print java doc: "string's characters are converted into bytes according to the platform's default character encoding")
In case if I would use PrintWriter(or PrintStream) as a parameter then i cannot use BufferedWriter and writing to the file would be slower.
It is possible to use a same code (and same methods) for writing to a file and to System.out?
(This is for my school project so I want it to be a "pure" and fully correct)
What you're trying to accomplish, is to treat the fileoutput and the consoleoutput the same. This is possible, because System.out is a PrintStream, and you can create a PrintStream for a file like this
new PrintStream(yourFile)
or insert a BufferedOutputStream in between
new PrintStream(new BufferedOutputStream(new FileOutputStream(yourFile))).
Note that this is not needed, because PrintStream does buffer its output itself.
I would create a variable (global or not), representing the current output.
This might be a PrintStream, either System.out, or a PrintStream around a FileOutputStream, whatever you desire. You would then pass this stream to the write method or call the print methods on it directly.
The advantage is that you can easily switch this without much code modification, you can redirect it wherever you wan't. It's no problem to redirect it to a file and System.out! You wouldn't get that pure flexibility with the way you're writing the method currently.
You could (not saying you should), also redirect System.out directly, using System.setOut. This however is bad style, because it is quite uncommon and might confuse everyone else, if they have not seen the call to System.setOut.
System.out is an object of type PrintStream. So yes, you can write to
System.out and/or to another file using exactly the same methods. Just
construct a PrintStream object and direct it to your file. So declare
your out variable as PrintStream to start with.
See also:
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html
http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html

PrintStream vs PrintWriter

I have searched the site and have found some answers, but i'm having trouble understanding the difference between these two classes. Can someone explain the differences between these two classes?
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.
From the Javadoc for PrintWriter:
Prints formatted representations of objects to a text-output stream. This class implements all of the print methods found in PrintStream. It does not contain methods for writing raw bytes, for which a program should use unencoded byte streams.
Think of it this way: a PrintStream sits on top of some OutputStream. Since output streams deal with bytes rather than characters, the PrintStream must take responsibility for encoding characters into bytes. The OutputStream 'merely' writes the bytes out to a file/console/socket whatever.
A PrintWriter, on the other hand, sits on top of a Writer. Since the Writer is responsible for encoding characters into bytes, the PrintWriter does not do encoding. I just knows about newlines etc. (Yes, PrintWriters do have constructors that take Files and OutputStreams, but those are simply conveniences. For example, PrintWriter(OutputStream).
Creates a new PrintWriter, without automatic line flushing, from an existing OutputStream. This convenience constructor creates the necessary intermediate OutputStreamWriter, which will convert characters into bytes using the default character encoding.
BTW, In case you are thinking that the PrintWriter really doesn't have much utility, remember that both PrintWriter and PrintStream absorb IOExceptions from printing logic.
To add Matt's answer:
I compared PrintStream and PrintWriter,
the most useful part, the constructor ClassName(String fileName, String charsetName) and the print(), println(), printf()/format() functions are supported by both classes.
The differences are:
Since JDK1.0 vs JDK1.1
Constructors:
PrintStream(OutputStream out, boolean autoFlush, String charsetName)
PrintWriter(Writer wr)
PrintWriter(Writer wr, boolean autoFlush)
Methods inherited from FilterOutputStream/OutputStream vs Writer, the difference boils down to byte vs char:
PrintStream.write(byte[] buffer, int offset, int count)
PrintStream.write(byte[] buffer)
PrintStream.write(int oneByte)
PrintWriter.write(int oneChar)
PrintWriter.write(char[] buf)
PrintWriter.write(char[] buf, int offset, int count)
PrintWriter.write(String str)
PrintWriter.write(String str, int offset, int count)
PrintStream.printf() corresponds to PrintWriter.format()
It indeed looks like in 1.1. they thought out a better class, but could not remove the old 1.0 class without breaking existing programs.

Java: How can I read Reader multiple times?

If I call IOUtils.toString(reader); it returns correct string value. Second call returns "". Reset does not supported by reader
How can I solve this situation?
You can't make the Reader "re-readable" if it doesn't support mark() and reset(). But you could use the String returned from the call you've shown to create a StringReader any number of times, and read those as needed (or use mark() and reset() on a single instance to re-read it as needed.)
Use a java.io.Reader that does support reset, such as CharArrayReader (see http://download.oracle.com/javase/6/docs/api/java/io/CharArrayReader.html).
A BufferedReader also supports reset() of a limited number of characters if a mark is set.
More generally the markSupported method indicates whether the implementation of Reader you are using supports mark/reset (thanks to comment from Bala R pointing that out).

Why need PrintWriter?

I am really confused about the purpose of various io classes, for example, If we have BufferedWriter, why we need a PrintWriter?
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
while(s=br.readline()!=null) {
PrintWriter fs = new PrintWriter(new FileWriter(file));
fs.println(s);
}
if the BufferedWriter can not help? I just do not understand the difference between these io classes, can someone explain me?
They have nothing to do with each other. In all truth, I rarely use PrintWriter except to convert System.out temporarily. But anyway.
BufferedWriter, like BufferedReader/BufferedInputStream/BufferedOutputStream merely decorates the enclosed Writer with a memory buffer (you can specify the size) or accept a default. This is very useful when writing to slow Writers like network or file based. (Stuff is committed in memory and only occasionally to disk for example) By buffering in memory the speed is greatly increased - try writing code that writes to say a 10 mb file with just FileWriter and then compare to the same with BufferedWriter wrapped around it.
So that's BufferedWriter. It throws in a few convenience methods, but mostly it just provides this memory buffer.
PrintWriter mostly is a simple decorator that adds some specific write methods for various types like String, float, etc, so you don't have to convert everything to raw bytes.
Edited:
This already has come up
The PrintWriter is essentially a convenience class. If you want to quickly and easily blast out a line of text to e.g. a log file, PrintWriter makes it very easy.
Three features:
The print and println methods will take any data type and do the conversion for you. Not just String.
The relatively new format method is worth its weight in gold. Now it's as simple in Java as in C to output a line of text with C-style format control.
The methods never throw an exception! Some programmers are horrified at the possibility of never hearing about things going wrong. But if it's a throwaway program or doing something really simple, the convenience can be nice. Especially if output is to System.out or System.err which have few ways of going wrong.
The main reason to use the PrintWriter is to get access to the printXXX methods (like println(int)). You can essentially use a PrintWriter to write to a file just like you would use System.out to write to the console.
A BufferedWriter is an efficient way to write to a file (or anything else) as it will buffer the characters in Java memory before writing to the file.

Java's [Input|Output]Streams' one-method-call-for-each-byte: a performance problem?

[Input|Output]Streams exist since JDK1.0, while their character-counterparts Readers|Writers exist since JDK1.1.
Most concepts seem similar, with one exception: the base classes of streams declare an abstract method which processes one single byte at a time, while base readers/writers classes declare an abstract method which processes whole char-arrays.
Thus, given that I understand it correctly, every overridden stream class is limited to process single bytes (thereby performing at least one method call for each byte!), while overridden readers/writers only need a method call per array(-buffer).
Isn't that a huge performance problem?
Can a stream be implemented as subclass of either InputStream or OutputStream, but nevertheless be based on byte-arrays?
Actually, subclasses of InputStream have to override the method that reads a single byte at a time, but also can override others methods that read while byte-arrays. I think that's actually the case for most of the Input/Output streams.
So this isn't much of a performance problem, in my opinion, and yes, you can extend Input/Output stream and be based on byte-arrays.
Single byte reading is almost always a huge performance problem. But if you read the API docs of InputStream, you see that you HAVE TO override read(), but SHOULD also override read(byte[],int,int). Most code that uses any kind of InputStream calls the array style method anyway, but the default implementation of that function is just implemented by calling read() for every byte, so the negative performance impact.
For OutputStream the same holds.
As Daniel said, you must override read(), since client might use it directly, but you also should override read (byte[],int,int).
However, I doubt if you should be concerned with performance since the jvm can and will inline that method for you. Most of all, it doesn't seem like an issue to me.
Also, most readers use some underlying input stream behind the scene, so in any case those char-array based methods end up calling read(byte[],int,int) or even read() directly.
Note that Readers/Writers are for reading characters which can be made of more than one byte such as unicode characters. Streams on the other hand are more suitable when you're dealing with non-string (binary) data.
Apart from that, InputStream and OutputStream also have methods to read/write an entire array of bytes.
performance wise, if you wrap it with BufferedInputStream, JVM should be able to optimize the overhead of single byte read method calls to nothing, i.e. it's as fast as if you do the buffering yourself.

Categories

Resources