Michael Dorner
Michael Dorner

Reputation: 20175

From ByteBuffer to object

I want to convert a ByteBuffer (coming from a network stream and consisting e.g. of <double, double, bool, int> in that order) to an object e.g. of the given class AClass:

class AClass {
    public double aDouble;
    public double anotherDouble;
    public boolean aBoolean;
    public int anInteger;
}

We can assume, that

Is there an efficient (cast-like) way to convert the ByteBuffer to a given class object? Can I use some kind of a mask to mask the primitive data types?

mask:  | double  | double  |bool| ...
bytes: | - - - - | - - - - | -  | ...

Basically I am looking for something like Matlab's memmapfile function. Thanks alot.

Upvotes: 1

Views: 5760

Answers (2)

david
david

Reputation: 1016

The reasonably idiomatic and maintainable way to do something like this, available since Java 1.0, is with a DataInputStream...

void fillFromBytes(byte[] arr) throws IOException {
  DataInputStream dis = new DataInputStream(new ByteArrayInputStream(arr));
  aDouble = dis.readDouble();
  anotherDouble = dis.readDouble();
  aBoolean = ( dis.readByte() != 0 );
  ...

Since you're already working with a ByteBuffer (since 1.4), however, you have a range of methods directly on it such as getDouble(). That gives you similar methods for reading primitive data from arbitrary offsets...

void fillFromBytes(ByteBuffer buf) throws IOException {
  aDouble = buf.getDouble();
  anotherDouble = buf.getDouble();
  aBoolean = ( buf.getByte() != 0 );
  ...

You can deal with padding by skipping to an absolute position after it, e.g.

 anotherDouble = buf.getDouble(0x24);

or by skipping over it a byte at a time:

 int npad = buf.getShort();
 for (int i=0 ; i < npad; i++) buf.getByte();

Upvotes: 2

Peter Lawrey
Peter Lawrey

Reputation: 533700

You can do this with Unsafe. It supports copying of data directly between native memory and objects. However in Java you have no control over the order of fields, nor how much padding is used. e.g. the boolean to can placed after the int to improve alignment and packing of the object, or padding can be added between fields.

You are better off copying the field one at a time. While this might seem slower, in reality the main issue is bring the data into the L1 cache and the copy of each field is pretty quick by comparison.

Upvotes: 4

Related Questions