Reputation: 20175
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
ByteBuffer
is known and constant (e.g. 4 bytes for double
, 1 byte for boolean
).ByteBuffer
is always the same.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
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
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