Java 从ByteBuffer到object
我想将Java 从ByteBuffer到object,java,bytebuffer,unsafe,Java,Bytebuffer,Unsafe,我想将字节缓冲区(来自网络流,按该顺序由组成)转换为对象,例如给定类的对象AClass: class AClass { public double aDouble; public double anotherDouble; public boolean aBoolean; public int anInteger; } 我们可以假设 ByteBuffer中每个基元数据类型的大小都是已知的且是恒定的(例如,double为4字节,boolean为1字节) Byte
字节缓冲区
(来自网络流,按该顺序由
组成)转换为对象,例如给定类的对象AClass
:
class AClass {
public double aDouble;
public double anotherDouble;
public boolean aBoolean;
public int anInteger;
}
我们可以假设
中每个基元数据类型的大小都是已知的且是恒定的(例如,ByteBuffer
为4字节,double
为1字节)boolean
中基本数据类型的顺序始终相同ByteBuffer
字节缓冲
转换为给定的类对象?我可以使用某种掩码来屏蔽基本数据类型吗
mask: | double | double |bool| ...
bytes: | - - - - | - - - - | - | ...
基本上,我在寻找类似函数的东西。非常感谢。您可以用不安全的工具完成此操作。它支持直接在本机内存和对象之间复制数据。但是,在Java中,您无法控制字段的顺序,也无法控制使用了多少填充。e、 g.
boolean
to可以放在int
之后,以改进对象的对齐和打包,或者可以在字段之间添加填充
最好一次复制一个字段。虽然这看起来比较慢,但实际上主要的问题是将数据带到一级缓存中,相比之下,每个字段的副本都非常快。您可以使用不安全的方法来完成这一操作。它支持直接在本机内存和对象之间复制数据。但是,在Java中,您无法控制字段的顺序,也无法控制使用了多少填充。e、 g.
boolean
to可以放在int
之后,以改进对象的对齐和打包,或者可以在字段之间添加填充
最好一次复制一个字段。虽然这看起来比较慢,但实际上主要的问题是将数据放入一级缓存,相比之下,每个字段的副本都非常快。从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开始),因此可以直接使用一系列方法,例如。这为您提供了从任意偏移量读取基本数据的类似方法
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();
int npad=buf.getShort();
对于(inti=0;i
从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开始),因此可以直接使用一系列方法,例如。这为您提供了从任意偏移量读取基本数据的类似方法
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();
int npad=buf.getShort();
对于(inti=0;i
否,编写您自己的转换器,从字节缓冲区中提取并使用相应的值调用AClass
中的某些构造函数或setter。此外,挑剔,但通常浮点值是4字节或更多,双字节值是8字节或更多。这是一种不寻常的情况:它直接来自某些硬件(不是标准PC)。@MichaelDorner:Javadouble
始终是8个字节;Javafloat
始终是4个字节。它与硬件无关。我指的是包含浮点数和双精度(字节值)的ByteBuffer。不,编写您自己的转换器,从ByteBuffer
提取并调用一些构造函数或setter从AClass
中选择相应的值。此外,挑剔,但通常float
为4字节或更多,double
为8字节或更多。这是一种不寻常的情况:它直接来自某些硬件(不是标准PC)@MichaelDorner:Javadouble
始终是8个字节;Javafloat
始终是4个字节。它与硬件无关。我指的是包含浮点数和double(字节值)的ByteBuffer。你这样做是什么意思?它们如何从ByteBuffer
到AClass
,使用Unsafe
?@SotiriosDelimanolis仅供你参考。在64位JVM上,你可以这样做。Unsafe.copyMemory(null,((DirectBuffer)ByteBuffer.address(),object,12,16)
假设您想从ByteBuffer的开头复制16个字节,对象的头是12个字节长。但是,除非您知道对象的布局(例如,一个基本数组可能没问题)。我也喜欢生活在危险之中。我在eclipse和mis上用autocomplete查看了不安全的方法sed那一个。很好。我必须在我还能的时候试试。你这么做是什么意思?他们如何从ByteBuffer
到AClass
,使用Unsafe
?@SotiriosDelimanolis仅供你参考。在64位JVM上你可以这样做。theUnsafe.copyMemory(null,((DirectBuffer)ByteBuffer)。address(),object,12,16)
假设您想从ByteBuffer的开头复制16个字节,对象的头是12个字节长。但是,除非您知道对象的布局(例如,一个基本数组可能没问题)。我也喜欢生活在危险之中。我在eclipse和mis上用autocomplete查看了不安全的方法sed那一个。非常好。我必须在我还能的时候试试。谢谢,工作很好,但这远远不够高效:每个转换后面都有两个构造函数调用。谢谢,工作很好,但这远远不够高效:每个转换后面都有两个构造函数调用。