Java BufferedOutputStream

Jakob Jenkov
Last update: 2019-10-20

The Java BufferedOutputStream class, java.io.BufferedOutputStream, is used to capture bytes written to the BufferedOutputStream in a buffer, and write the whole buffer in one batch to an underlying Java OutputStream for increased performance. Buffering can speed up IO quite a bit, especially when writing data to disk access or network.

Create a BufferedOutputStream

To add buffering to your OutputStream's simply wrap them in a BufferedOutputStream. Here is an example of wrapping an OutputStream in a BufferedOutputStream:

OutputStream output = new BufferedOutputStream(
                      new FileOutputStream("c:\\data\\output-file.txt"));

Simple, isn't it?

Setting Buffer Size of a BufferedOutputStream

You can set the buffer size to use internally by in a Java BufferedOutputStream. You provide the size as a constructor parameter, like this:

int bufferSize = 8 * 1024;
OutputStream output = new BufferedOutputStream(
                      new FileOutputStream("c:\\data\\output-file.txt"),
                          bufferSize
);

This example sets the internal buffer to 8 KB. It is best to use buffer sizes that are multiples of 1024 bytes. That works best with most built-in buffering in hard disks etc.

Except for adding buffering to your input streams, the Java BufferedOutputStream behaves exactly like an OutputStream. The only difference is that you may need to call flush() if you need to be absolutely sure that the data written until now is flushed out of the buffer and onto the network or disk.

Optimal Buffer Size for a BufferedOutputStream

You should make some experiments with different buffer sizes to find out which buffer size seems to give you the best performance on your concrete hardware. The optimal buffer size may depend on whether you are using the Java BufferedOutputStream with a disk or network OutputStream.

With both disk and network streams, the optimal buffer size may also depend on the concrete hardware in the computer. If the hard disk is anyways writing a minimum of 4KB at a time, it's stupid to use less than a 4KB buffer. It is also better to then use a buffer size that is a multiple of 4KB. For instance, using 6KB would be stupid too.

Even if your disk writes blocks of e.g. 4KB at a time, it can still be a good idea to use a buffer that is larger than this. A disk is good at writing data sequentially - meaning it is good at writing multiple blocks that are located after each other. Thus, using a 16KB buffer, or a 64KB buffer (or even larger) with a BufferedOutputStream may still give you a better performance than using just a 4KB buffer.

To find the optimal BufferedOutputStream buffer size, find out the block size your hard disk writes in, and make the buffer a multiple of that size. You will definitely have to experiment to find the optimal buffer size. Do so by measuring write speeds with different buffer sizes.

write()

To write data to a Java BufferedOutputStream you can use its write() method. The write() method takes an int which contains the byte value of the byte to write. Thus, only the lower 8 bit of the passed int actually gets written to the BufferedOutputStream destination. Here is an example of writing data to a Java BufferedOutputStream using its write() method:

BufferedOutputStream bufferedOutputStream =
    new BufferedOutputStream(new FileOutputStream("c:\\data\\output-text.txt"));

bufferedOutputStream.write(123);

This example writes the byte value 123 to the given Java BufferedOutputStream.

Writing Byte Arrays

Since the Java BufferedOutputStream is a subclass of OutputStream, you can write arrays of bytes to the BufferedOutputStream too, instead of just a single byte at a time. Here is an example of writing an array of bytes to a Java BufferedOutputStream :

BufferedOutputStream bufferedOutputStream =
    new BufferedOutputStream(new FileOutputStream("c:\\data\\output-text.txt"));

byte bytes =  new byte[]{1,2,3,4,5};

outputStream.write(bytes);

flush()

When you write data to a Java BufferedOutputStream the data is cached internally in a byte buffer until the byte buffer is full, at which time the whole buffer is written to the underlying OutputStream.

If you want to make sure that all written data is written to disk without having to close the BufferedOutputStream you can call its flush() method. Calling flush() will make sure that all data which has been written to the BufferedOutputStream so far, is fully written to the underlying OutputStream too, plus flush() will also have been called on the underlying OutputStream. Here is an example of calling the Java BufferedOutputStream flush() method:

OutputStream outputStream =
    new BufferedOutputStream(new FileOutputStream("c:\\data\\output-text.txt"));

byte bytes =  new byte[]{1,2,3,4,5};

outputStream.write(bytes);

outputStream.flush()

Closing a BufferedOutputStream

Once you are done writing data to a Java BufferedOutputStream you should close it. You close an BufferedOutputStream by calling its close() method. Closing a BufferedOutputStream also closes the underlying OutputStream that the BufferedOutputStream is reading data from. Here is an example of closing a Java BufferedOutputStream:

BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                      new FileOutputStream("c:\\data\\output-file.txt"));

while(hasMoreData()) {
    int data = getMoreData();
    bufferedOutputStream.write(data);
}
bufferedOutputStream.close();

The concrete implementations of hasMoreData() and getMoreData() are left out, but they are not really super important to understand the principle of this example. What matters is, that once the while loop ends, and you are done writing data to the BufferedOutputStream, its close() method is called, which closes the BufferedOutputStream .

The above example is not fully robust though. In case the write() method throws an exception, the close() method will never get called. The exception will make the program exit whatever method the above code is located in.

Instead, you should use the Java try with resources construct to close the BufferedOutputStream. Here is an example that closes a Java BufferedOutputStream using the try-with-resources construct:

try( BufferedOutputStream bufferedOutputStream =
        new BufferedOutputStream(new FileOutputStream("c:\\data\\output-text.txt"))) {

    while(hasMoreData()) {
        int data = getMoreData();
        output.write(data);
    }
}

Once the try block is exited, the close() method of the BufferedOutputStream is called automatically, because the BufferedOutputStream was declared inside the parentheses of the try block. Even if an exception is thrown from inside the try block, the close() method is still called before the exception is propagated up the call stack.

Jakob Jenkov

Featured Videos

Java Generics

Java ForkJoinPool

P2P Networks Introduction



















Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next