Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从ByteBuffer到object_Java_Bytebuffer_Unsafe - Fatal编程技术网

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
    中每个基元数据类型的大小都是已知的且是恒定的(例如,
    double
    为4字节,
    boolean
    为1字节)
  • 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:Java
double
始终是8个字节;Java
float
始终是4个字节。它与硬件无关。我指的是包含浮点数和双精度(字节值)的ByteBuffer。不,编写您自己的转换器,从
ByteBuffer
提取并调用一些构造函数或setter从
AClass
中选择相应的值。此外,挑剔,但通常
float
为4字节或更多,
double
为8字节或更多。这是一种不寻常的情况:它直接来自某些硬件(不是标准PC)@MichaelDorner:Java
double
始终是8个字节;Java
float
始终是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那一个。非常好。我必须在我还能的时候试试。谢谢,工作很好,但这远远不够高效:每个转换后面都有两个构造函数调用。谢谢,工作很好,但这远远不够高效:每个转换后面都有两个构造函数调用。