Home | FAQ | Contact me

Java's ByteBuffer

In the buffer, capacity refers to the total size. Position refers to the current position in the buffer. Limit refers to the end of the buffer's capacity in write mode, to the end of the range of bytes written in write mode—which might not be the whole buffer if writing never reached total capacity. A buffer has mode—either read or write.

A word on direct versus not-direct...

This class offers method allocate() and allocateDirect(). The former is the more frequently used one and its allocations live in the JVM's garbage-collectible heap. The latter, however, is not garbage-collectible. This sort of allocation is also very expensive, but the result is faster and more appropriate usage for certain types of native I/O operations (that I don't discuss here). See Direct vs. non-direct buffers in the Javadoc for java.nio.ByteBuffer.

Java (java.nio) ByteBuffer is useful whenever one needs to perform fast, low-level I/O such as when implementing a TCP/IP protocol, writing a database, etc. (This is what we're doing.) Here's a good summary. Here are some useful operations:

Examples: testing a ByteBuffer

ByteBuffers are not typically used to hold string per se, though they can. Usually, you put "data" into a buffer (integers, longs, floats, etc.). However, here is a test that illustrates putting a string into a ByteBuffer:

@Test
public void testByteBufferWithAString()
{
  final String TEST_STRING = "This is a test.";
  final int    LENGTH      = TEST_STRING.length();
  System.out.println( "         TEST_STRING=" + TEST_STRING );
  System.out.println( "              LENGTH=" + LENGTH );
  System.out.println( "  Allocate the ByteBuffer:");
  ByteBuffer buffer = ByteBuffer.allocate( LENGTH );
  System.out.println( "  buffer.remaining()=" + buffer.remaining() ); // this is limit-position
  System.out.println( "      buffer.limit()=" + buffer.limit() );
  System.out.println( "  Copy the test string contents into the buffer:" );
  buffer.put( TEST_STRING.getBytes() );
  System.out.println( "  Now, flip the buffer, then print its contents:" );
  buffer.flip();
  while( buffer.hasRemaining() )                                     // as long as position < limit
    System.out.print( ( char ) buffer.get() );
  System.out.println();
  System.out.println( "  buffer.remaining()=" + buffer.remaining() );
  System.out.println( "      buffer.limit()=" + buffer.limit() );
}

Output:

         TEST_STRING=This is a test.
              LENGTH=15
  Allocate the ByteBuffer:
  buffer.remaining()=15
      buffer.limit()=15
  Copy the test string contents into the buffer:
  Now, flip the buffer, then print its contents:
This is a test.
  buffer.remaining()=0
      buffer.limit()=15

Here a ByteBuffer is used to store a short integer:

@Test
public void testByteBufferWithAShortInside()
{
  final Short aShort = 23;
  System.out.println( "  Allocate the ByteBuffer:");
  ByteBuffer buffer = ByteBuffer.allocate( Short.SIZE );
  System.out.println( "  buffer.remaining()=" + buffer.remaining() );
  System.out.println( "      buffer.limit()=" + buffer.limit() );
  System.out.println( "  Copy the test short into the buffer:" );
  buffer.putShort( aShort );
  System.out.println( "  Now, flip the buffer, then print its contents:" );
  buffer.flip();
  while( buffer.hasRemaining() )
    System.out.print( buffer.getShort() + "" );
  System.out.println();
  System.out.println( "  buffer.remaining()=" + buffer.remaining() );
  System.out.println( "      buffer.limit()=" + buffer.limit() );
}

Output:

  Allocate the ByteBuffer:
  buffer.remaining()=16
      buffer.limit()=16
  Copy the test short into the buffer:
  Now, flip the buffer, then print its contents:
23
  buffer.remaining()=0
      buffer.limit()=2