Java difference between FileWriter and BufferedWriter

What's the difference between those? I'm just learning Java ATM, but it seems like I can write to a file both ways i.e. (I didn't copy the try-catch block here.)

FileWriter file = new FileWriter("foo.txt");
file.write("foobar");
file.close();

and

FileWriter file = new FileWriter("foo.txt");
BufferedWriter bf = new BufferedWriter(file);
bf.write("foobar");
bf.close();

I understand the concept of buffering the data first, so does that mean the first example writes the characters one by one and the second first buffers it to the memory and writes it once?

114725 次浏览

BufferedWriter is more efficient. It saves up small writes and writes in one larger chunk if memory serves me correctly. If you are doing lots of small writes then I would use BufferedWriter. Calling write calls to the OS which is slow so having as few writes as possible is usually desirable.

You are right. Here is how write() method of BufferedWriter looks:

public void write(int c) throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar >= nChars)
flushBuffer();
cb[nextChar++] = (char) c;
}
}

As you can see it indeed checks whether the buffer is full (if (nextChar >= nChars)) and flushes the buffer. Then it adds new character to buffer (cb[nextChar++] = (char) c;).

From the Java API specification:

FileWriter

Convenience class for writing character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable.

BufferedWriter

Write text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings.

http://docs.oracle.com/javase/1.5.0/docs/api/java/io/BufferedWriter.html

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.

BufferedWriter is more efficient if you

  • have multiple writes between flush/close
  • the writes are small compared with the buffer size.

In your example, you have only one write, so the BufferedWriter just add overhead you don't need.

so does that mean the first example writes the characters one by one and the second first buffers it to the memory and writes it once

In both cases, the string is written at once.

If you use just FileWriter your write(String) calls

 public void write(String str, int off, int len)
// some code
str.getChars(off, (off + len), cbuf, 0);
write(cbuf, 0, len);
}

This makes one system call, per call to write(String).


Where BufferedWriter improves efficiency is in multiple small writes.

for(int i = 0; i < 100; i++) {
writer.write("foorbar");
writer.write(NEW_LINE);
}
writer.close();

Without a BufferedWriter this could make 200 (2 * 100) system calls and writes to disk which is inefficient. With a BufferedWriter, these can all be buffered together and as the default buffer size is 8192 characters this become just 1 system call to write.

In unbuffered Input/Output(FileWriter, FileReader) read or write request is handled directly by the underlying OS. https://hajsoftutorial.com/java/wp-content/uploads/2018/04/Unbuffered.gif

This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive. To reduce this kind of overhead, the Java platform implements buffered I/O streams. The BufferedReader and BufferedWriter classes provide internal character buffers. Text that’s written to a buffered writer is stored in the internal buffer and only written to the underlying writer when the buffer fills up or is flushed. https://hajsoftutorial.com/java/wp-content/uploads/2018/04/bufferedoutput.gif

More https://hajsoftutorial.com/java-bufferedwriter/