我想将ByteBuffer
(来自网络流,并且按照该顺序由<double, double, bool, int>
组成)转换为对象,例如给定的类AClass
:
class AClass {
public double aDouble;
public double anotherDouble;
public boolean aBoolean;
public int anInteger;
}
我们可以假设,
ByteBuffer
中每个原始数据类型的大小是已知且常量的(例如double
为4个字节,boolean
为1个字节)。ByteBuffer
中原始数据类型的顺序始终相同。是否有一种将ByteBuffer
转换为给定类对象的高效(类似强制转换)方法?我可以使用某种掩码来掩盖原始数据类型吗?
mask: | double | double |bool| ...
bytes: | - - - - | - - - - | - | ...
基本上我正在寻找像Matlab's memmapfile
这样的功能。非常感谢。
答案 0 :(得分:4)
您可以使用不安全来执行此操作。它支持直接在本机内存和对象之间复制数据。但是在Java中,您无法控制字段的顺序,也无法控制使用的填充量。例如可以在boolean
之后放置int
以改善对象的对齐和打包,或者可以在字段之间添加填充。
最好一次复制一个字段。虽然这看起来可能比较慢,但实际上主要问题是将数据带入L1缓存中,相比之下,每个字段的副本相当快。
答案 1 :(得分:2)
从Java 1.0开始,可以通过DataInputStream实现像这样的合理惯用和可维护的方式......
void fillFromBytes(byte[] arr) throws IOException {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(arr));
aDouble = dis.readDouble();
anotherDouble = dis.readDouble();
aBoolean = ( dis.readByte() != 0 );
...
但是,由于您已经在使用ByteBuffer(自1.4起),因此您可以直接使用一系列方法,例如getDouble()。这为您提供了从任意偏移中读取原始数据的类似方法......
void fillFromBytes(ByteBuffer buf) throws IOException {
aDouble = buf.getDouble();
anotherDouble = buf.getDouble();
aBoolean = ( buf.getByte() != 0 );
...
您可以通过跳到其后的绝对位置来处理填充,例如
anotherDouble = buf.getDouble(0x24);
或一次跳过一个字节:
int npad = buf.getShort();
for (int i=0 ; i < npad; i++) buf.getByte();