JaVa
   

The ByteBuffer Class

A ByteBuffer is a nice wrapper around simple arrays of bytes that makes it really easy for us to send and receive primitive data types, as well as more complex information. Let's look at a simple example of how we can use ByteBuffer.

Code Listing 18-1: ByteBufferExample.java
import java.nio.*;
public class ByteBufferExample
{
 public static void main(String args[])
 {
 String tempString = "Hello";
 byte[] byteText = tempString.getBytes();
 // Create a byte buffer
 ByteBuffer byteBuffer = ByteBuffer.allocate(4 + 4 + 8 +
 byteText.length); // int + int + double + 5 character string
 // Add an int to the ByteBuffer...
 byteBuffer.putInt(15);
 // Add a double...
 byteBuffer.putDouble(10.6);
 // Finally add the string...
 byteBuffer.putInt(byteText.length);
 byteBuffer.put(byteText);
 // Rewind the ByteBuffer back to the start...
 byteBuffer.rewind();
 // Now get the info back from the ByteBuffer...
 System.out.println("Integer was "+byteBuffer.getInt());
 System.out.println("Double was "+byteBuffer.getDouble());
 final int MAX_TEXT_LENGTH = 256;
 byte[] buffer = new byte[MAX_TEXT_LENGTH];
 int length = byteBuffer.getInt();
 byteBuffer.get(buffer, 0, Math.min(length, MAX_TEXT_LENGTH));
 System.out.println("String was "+new String(buffer, 0,
 length));
 }
}


Java End example

When you run the example, you should see the following output:

Java Click To expand
Screenshot-1: ByteBuffer example

Let's now look at the source code in detail so we can see how it works. First we include the NIO package, which is java.nio.*. This can be seen here:

import java.nio.*;


Then we create our main class called ByteBufferExample and also our main method. Once we do this, we assign a String object called tempString to the value Hello. Then we retrieve the string data as bytes and store this in a byte array called byteText. We then allocate a ByteBuffer by calling the static allocate method, which is a member of the ByteBuffer class. This can be seen here:

ByteBuffer byteBuffer = ByteBuffer.allocate(4 + 4 + 8 +
 byteText.length);


Note that once a ByteBuffer has been allocated, it is then not possible to increase its size; however, it is possible to reduce the size by placing a limit on it using the limit(int) method. Also, we can obtain the current limit by calling the limit() method (with no parameters). So in this example, we have allocated enough space within the ByteBuffer to hold two ints (four bytes each), a double (eight bytes), and a five-character string (five bytes). Here is a table of the sizes of primitive data types in bytes:

Data Type

Size in Bytes

byte

1

char

2

short

2

int

4

float

4

long

8

double

8

Once the ByteBuffer is allocated, we then use the putInt method to place an integer value at the start of the buffer. In this example, we have used the value 15. It will appear in the buffer at the start, which can be seen in the following diagram (note that each square represents one byte):

Java Click To expand

Next we call the putDouble method, which will append a double value to the ByteBuffer. When the int value was added, the current position of the buffer is set to the end of the first four bytes, so when the double is added it will look like the following:

Java Click To expand

Next we add an integer value that represents the length of the string that we are about to add in bytes, which we retrieved from our byte array byteText using the length member. Therefore, after we add this, the ByteBuffer will look as follows:

Java Click To expand

Then we finally add our string Hello to the ByteBuffer using the put method, which can take an array of bytes as a parameter. Therefore, we can simply pass in our byteText byte array and fill the remaining five bytes; hence, the final ByteBuffer will look as follows:

Java Click To expand

Now all our data is in the ByteBuffer and the position of the ByteBuffer is at the end of it. So to enable us to access any of the data, we first need to "rewind" it, so the position is at the start. This is done conveniently via the rewind method, which can be seen here:

byteBuffer.rewind();


So the position of the ByteBuffer is then back to the start. Now we can start retrieving information from it using the equivalent get methods. First, we will get the integer value back by calling the getInt method, which can be seen in the following line of code:

System.out.println("Integer was "+byteBuffer.getInt());


Then, as with the put method, the current position of the ByteBuffer is moved to the end of the int value (i.e., four bytes forward), so we can then extract and print our double value using this next line of code:

System.out.println("Double was "+byteBuffer.getDouble());


Finally, we retrieve our string by first retrieving the length of the string, which is stored within the ByteBuffer as an integer value. Then, once we have this value, we can call the get method, passing in a byte array and limiting the amount of bytes to retrieve to five. To get our string from the bytes, we can then create a new String object from the array of bytes by passing the array of bytes into the string's constructor. This can be seen here:

System.out.println("String was "+new String(buffer, 0, length));


NoteĀ 

It is also possible to chain the put methods so instead of having the four lines as we did in the previous example, we could have the following to add our data into the ByteBuffer.

byteBuffer.putInt(15).putDouble(10.6).putInt(byteText.length).put
 (byteText);
JaVa
   
Comments