Search this site

 Home  I/O  Buffering  Character streams  NIO intro  Buffers  Channels  Buffer performance

Search this site:
Threads Database Profiling Regular expressions Random numbers Compression Exceptions C Equivalents in Java

 What do you think of this article? Did it help you? Found a mistake? Feedback and suggestions here

Reading from and writing to a ByteBuffer

Once we've created a ByteBuffer, the first thing we probably want to do is read or write some data to it.

Reading/writing a byte at the current position

The methods get() and put() read and write a byte respectively at the current position and then automatically update the position. Thus, in the simplest case of just wanting to read sequentially through data in the buffer (or write data sequentially), this can be accomplished with some extremely straightforward code.

ByteBuffer bb = ByteBuffer.wrap(...);
byte b1 = bb.get(); // read the first byte
byte b2 = bb.get(); // read the second byte
...

A syntax reminder: if we're passing in a byte literal (that is, where we just "hard code" a value in the code rather than passing a variable name), we need to put an explicit cast:

bb.put((byte) 40);

Reading/writing at a particular offset

Supposing you don't want to read/write at the current position? Well, there are two options:

  • calling the position() method, we can change the current position; subsequent get()/put() operations will take place from there (but then still updating the position each time as before);
  • we can pass in an explicit offset to the get() and put() methods.

So for example, this line will write the byte 32 to position 140:

buff.put(140, (byte) 32);

Note that these offset-specific put() and get() operations don't move the buffer's current position.

Reading/writing unsigned bytes

A slight complication in Java is that, perhaps contrary to common sense, the byte data type is always signed. What that means is that if you try and read/write the byte 128, when converted to a Java byte, this will actually come out as -128; byte 129 will actually come out as -127 etc. With some slightly klutzy code we can work round the problem:

  • to write an unsigned byte, we hold or calculate the value as an int and then simply cast to a byte;
  • to read an unsigned byte, we make sure we are reading into an int (or at least, something bigger than a byte), and then AND with 255 (0xff in hex).

This is what the latter code looks like:

int unsignedByte = bb.get() & 0xff;

This works because whenever you perform bitwise operations in Java, both operands (the things either side of the &) are converted to (at least) an int. Initially, a negative byte will be converted to a negative int (the sign is preserved or what is technically called sign extended). Then, ANDing with 255 (the maximum positive number that can fit in an 8-bit byte) in effect "chops off" the higher up bits that mark the int as negative.

Reading/writing other types

A key feature of a ByteBuffer is actually that you can efficiently write types other than a byte. On the next page, we look at reading and writing non-byte types in a ByteBuffer.

comments powered by Disqus

Written by Neil Coffey. Copyright © Javamex UK 2012. All rights reserved.