Java: Working with Buffers

Buffers can be very useful in java since they can speed up I/O operations considerably. Basically, a buffer is a space allocated into memory for bytes, chars, and other data types to be entered. I have found buffers to be really useful when writing client/server applications.

Below is an example of how to create a buffer:

* Buffer size
int BUFFER_SIZE = 100;

* Allocates a ByteBuffer
* with a size of a 100
ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);

* Makes an IntBuffer
IntBuffer intBuffer = IntBuffer.allocate(BUFFER_SIZE);

* Makes a Direct CharBuffer
CharBuffer charBuffer = CharBuffer.allocateDirect(BUFFER_SIZE);

In order for a buffer to function properly, it must have three different markers: position, limit and capacity.

Capacity: Capacity is the number set with the allocate(BUFFER_SIZE). That is basically how big the buffer is.

Limit: The limit of the buffer is the index of the first element that should not be read or written in the buffer. The limit of the buffer cannot be negative or greater that its capacity.

Position: The position of the buffer is the place that the buffer is in the next element to be read/written.

The different methods that edit the buffer just move those markers around. There are four methods with which you should be familiar:


clear(); The clear method, when applied to a buffer, sets the limit to the capacity and the position to 0. All that that means that when new data is added to the buffer it will overwrite the old data.

compact(); The compact method moves the elements between the current position and the limit to the beginning of the buffer.

flip(); The flip method needs to be called before reading the date from the buffer. When a flip is called, the limit is set to the current position, and the position is set to 0.

rewind(); The rewind method sets the position to zero again in case you want to make the buffer ready for another draining. You would need to flip the buffer first, though.

Direct vs. nonDirect buffers: Buffers can be either direct or nonDirect.
Direct: Creating a direct buffer simply means that the buffer is allocated inside the native data structure. That means that data can be transferred to native resources without having to go trough the java data structure. That can have a really good impact on performance.

NonDirect: If you create a buffer that will not interact with native resource (e.g., just to store a String), you should use a NonDirect Buffer.

Adding to a Buffer: When adding data to a buffer, you can use the wrap() method;
String string = "Text to be added";
CharBuffer charBuffer = CharBuffer.allocate(string.length());

Adding to a Buffer: When adding data to a buffer you can use the wrap() method. Note that when a buffer is created by wrapping, it is never direct.

* wraps a string inside an buffer.
String string = "Text to be added";
CharBuffer charBuffer = CharBuffer.allocate(string.length());

or you could wrap entire blocks of data in a form of an array:

* takes a byte array and wraps it into a buffer.
byte[] data = “Text to be added”.getBytes(“UTF-8”);
ByteBuffer buffer1 = ByteBuffer.wrap(data);

Draining a Buffer: Buffers can be drained into any data type:

* uses the get() method to fill a string.
String fromBuffer = “”;
while (buffer.hasRemaining()) {
fromBuffer += buffer.get();

Data Conversion: Data Conversion is an important aspect of buffers. You can use the factory methods to change a buffer from one type to another:

ByteBuffer byteBuffer = ByteBuffer.allocate(5);
IntBuffer intBuffer = byteBuffer.asIntBuffer();

Here is a list of conversions:


Buffers can be really useful. When creating a server/client application, Buffers can significantly increase your performance.


The Conversation

Follow the reactions below and share your own thoughts.

  • xastor

    This is nice, thank you.

  • Saber

    Thanks for this explanation,