Performance: BufferedOutputStream vs FileWriter
Asked Answered
P

2

9

I've always used a FileWriter to write text to a file in Java. Apparently you can also use a BufferedOutputStream as well. After reading both javadocs carefully, I can't seem to tell which was is faster/more efficient.

So I ask: is there a performance differential (even if minimal) between these two file I/O methods? If so, what are they and why? If not, why are they effectively the same?

Are there scenarios where one is preferred over the other? Thanks in advance!

Pommel answered 8/7, 2013 at 14:16 Comment(0)
A
10

If you really want to compare a FileWriter with a BufferedOutputStream to write a text file, the latter should be faster, since there a fewer I/O operations.

  • In the case of FileWriter, each call to a write method will be persisted at once (it's unbuffered).
  • In the case of a BufferedOutputStream, data will be written to disk, if the buffer is full (or the buffer is flushed explicity using the flush method).

But if you write text files, you should use a Writer; in this case we can compare a FileWriter with a BufferedWriter:

Looking at

FileWriter fw = new FileWriter(...)

and

BufferedWriter bw = new BufferedWriter(new FileWriter(...)

you have the same situation regarding the number of I/O operations.


A FileWriter uses a FileOutputStream internally. The reason to use a FileWriter is that it automatically uses the default character encoding, when you write to a file (a Java internal string is encoded into UTF-8 for example). If you use an OutputStream, you have to encode manually in each write:

So this example for a BufferedWriter:

bw.write("Hello");

corresponds to that example for a BufferedOutputStream:

bos.write("Hello".getBytes(Charset.forName("utf-8")));

if your default encoding is utf-8.

An OutputStream deals with (raw) bytes whereas a Writer deals with (text) characters.

Alyss answered 8/7, 2013 at 14:54 Comment(0)
A
3

A FileWriter writes text to files, while a BufferedOutputStream holds a buffer of arbitrary binary data in memory before writing it to another binary stream that you have to provide. They don't do the same thing at all, so comparing their performance is meaningless.

In general, buffering improves application throughput but adds latency. In the case of files, you can produce more output per second because you can transfer larger blocks to disk at once, so the overhead per byte is lower. On the other hand, while data is being buffered in memory it's not being written to disk, so it takes a longer time for any particular byte to get written to disk.

In the case of FileWriter, it already has an internal buffer that helps with encoding characters into bytes. Adding more buffering probably has little value.

Absalom answered 8/7, 2013 at 14:20 Comment(4)
Thanks @Absalom (+1) - interesting observation, but can you not write text to files with BufferedOutputStream?!? This article seems to think otherwise. If that article is true, then although FileWriter and BufferedOutputStream might be intended for 2 different uses, it is possible (and thus the point of my question) to compare their performance when writing text to a file.Pommel
Again, very interesting stuff @Joni! According to this SO question it seems possible to override the internal buffer that FileWriter uses. I'd like to try this out, if for nothing else, for my own personal amusement. For the life of me I can't figure out how to configure an OutputStreamWriter and a FileOutputStream and inject them into a FileWriter constructor - any ideas? And where would I specify the new buffer size? Thanks again for all the great help so far!Pommel
As you can see in the article, in order to write text with a BufferedOutputStream first they have convert any text into bytes manually, by caling getBytes, which is inconvenient and creates an array of bytes that becomes garbage immediatelyAbsalom
FileWriter is actually a subclass of OutputStreamWriter rigged so it can only write into a FileOutputStream, so if you want to customize some property you can just create an OutputStreamWriter connected to a FileOutputStream. There's no way to change the internal buffer size though. The default buffer of 8k is probably large enough for most applications.Absalom

© 2022 - 2024 — McMap. All rights reserved.