Ok so I am learning about I/O, and I found the following code in one of the slides. can someone please explain why there is a need to have a FileWrite, BufferedWriter and PrintWriter? I know BufferedWriter is to buffer the output and put it all at once but why would they use FileWriter and PrintWriter ? dont they pretty much do the same with a bit of difference in error handling etc?
And also why do they pass bw
to PrintWriter
?
FileWriter fw = new FileWriter (file);
BufferedWriter bw = new BufferedWriter (fw);
PrintWriter outFile = new PrintWriter (bw);
Presumably they're using a FileWriter
because they want to write to a file. Both BufferedWriter
and PrintWriter
have to be given another writer to write to - you need some eventual destination.
(Personally I don't like FileWriter
as it doesn't let you specify the encoding. I prefer to use FileOutputStream
wrapped in an OutputStreamWriter
, but that's a different matter.)
BufferedWriter
is used for buffering, as you say - although it doesn't buffer all the output, just a fixed amount of it (the size of the buffer). It creates "chunkier" writes to the underlying writer.
As for the use of PrintWriter
- well, that exposes some extra methods such as println
. Personally I dislike it as it swallows exceptions (you have to check explicitly with checkError
, which still doesn't give the details and which I don't think I've ever seen used), but again it depends on what you're doing. The PrintWriter
is passed the BufferedWriter
as its destination.
So the code below the section you've shown will presumably write to the PrintWriter
, which will write to the BufferedWriter
, which will (when its buffer is full, or it's flushed or closed) write to the FileWriter
, which will in turn convert the character data into bytes on disk.
From the Docs:
In general, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is advisable to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters. For example,
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
will buffer the PrintWriter's output to the file. Without buffering, each invocation of a print() method would cause characters to be converted into bytes that would then be written immediately to the file, which can be very inefficient.
You can understand from this that a BufferedWriter
is an efficient way to write stuff.
Writes text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings.
A FileWriter
object is passed to the BufferedWriter
as the intent here is to write to some output file using a BufferedWriter
.
And finally, a PrintWriter
is used for print*
methods like println()
.
PrintWriter from here
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.
from the above statement it seems the main reason to use PrintWriter is to get the access of all the methods of PrintStream
like println()
,println(char [] x)
etc.
BufferedWriter, You are right It's one of the best way to write to a file because it will buffered the character into the virtual memory before writing to a file directly and came up with a newLine()
method.
FileWriter from here
FileWriter is meant for writing streams of characters. For writing
streams of raw bytes, consider using a FileOutputStream
.
FileWriter
is simply to write plain text(without formatting) it doesn't use any buffer mechanism, whatever comes its way it just writes.
BufferedWriter
is a wrapper for Writer
classes to allow it to be able to use buffer functionality (to optimize IO).
PrintWriter
prints formatted text, you can provide format string along with the data to be printed, though it can directly work with any Writer/OutputStream
, just to provide buffering, Writer/OutputStream
is 1st passed to BufferedWriter
then to have formatted text is passed to PrintWriter
Usually, this kind of Writer chaining is about abstraction. PrintWriter
have some useful print
and println
methods that can be convenient if you want to print Strings and lines to a File. Working directly with FileWriter
, you would have to use a more "low level" API. And as you say BufferedWriter
is about buffering. So it's basically a matter of what you want to output to the file, and what level of abstraction you prefer.
The objects are wrapped in this order because you want to use the outermost PrintWriter for its more sophisticated formatting. BufferedWriter must be wrapped on something. So FileWriter, as a result, is what BufferedWriter wraps and is the innermost object.