Java: 非常高效地将字节流转换为对象
Java: Convert byte stream to objects very efficiently
我有一个 byte[],其中包含序列化的 C++ 数据类型(因此它具有标准 Java 序列化 类 无法理解的奇怪格式)。我已经创建了自己的反序列化器,它将标志与类型相匹配并将其转换为适当的对象,就像这样(输入可以是这样的 int64,值为 4 [3, 0, 0, 0, 0, 0, 0, 0, 4], 3 是 int64 的标志)
private final ByteBuffer byteWrapper;
// member ByteBuffer which is allocated in the ctor
ctor { byteWrapper = ByteBuffer.allocateDirect(8); }
// somewhere in the parse function, this case matches an int64
case 3:
{
return byteWrapper.wrap(ios.getBytes(8)).getLong();
}
其中 ios 包含完整的序列化数据,以便于阅读。现在这工作正常,但是高吞吐量对于这段代码非常重要而且我不是一个普通的 Java 程序员,所以我只是想知道是否有人对加快这个过程有任何建议,或者通过重新加工我所拥有的或完全使用不同的 classes/functions 或任何东西?内存不是问题,我只对速度感兴趣
不要将数据复制到新的缓冲区对象中。直接从ios缓冲区读取。
byte type = ios.get();
switch (type) {
case 3:
return ios.getLong();
}
ByteBuffer中的所有getter都会根据数据类型的长度增加position。 get()将位置加1,getLong()加8,getFloat()加4……直接用ios.getLong()就可以了。假设值是一个接一个写入的,新位置将指向下一个类型字节。所以可以直接调用ios.get()得到下一个类型
编辑:
如果ios 是一个InputStream,您可以使用DataInputStream 来读取。它还支持各种数据类型。
DataInputStream input = new DataInputStream(ios);
byte type = input.readByte();
switch (type) {
case 3:
return input.readLong();
}
在 Java 中,基本上有两个包提供您正在寻找的功能。 java.io 和 java.nio。 java.io 包含流,而 java.nio 包含缓冲区。 java.nio 更快,因为它使用非常低级的内存操作。如果您正在寻找速度,则应该使用它。这也意味着您应该尽可能将 ios 的类型更改为 ByteBuffer,然后使用我的第一种方法。
我有一个 byte[],其中包含序列化的 C++ 数据类型(因此它具有标准 Java 序列化 类 无法理解的奇怪格式)。我已经创建了自己的反序列化器,它将标志与类型相匹配并将其转换为适当的对象,就像这样(输入可以是这样的 int64,值为 4 [3, 0, 0, 0, 0, 0, 0, 0, 4], 3 是 int64 的标志)
private final ByteBuffer byteWrapper;
// member ByteBuffer which is allocated in the ctor
ctor { byteWrapper = ByteBuffer.allocateDirect(8); }
// somewhere in the parse function, this case matches an int64
case 3:
{
return byteWrapper.wrap(ios.getBytes(8)).getLong();
}
其中 ios 包含完整的序列化数据,以便于阅读。现在这工作正常,但是高吞吐量对于这段代码非常重要而且我不是一个普通的 Java 程序员,所以我只是想知道是否有人对加快这个过程有任何建议,或者通过重新加工我所拥有的或完全使用不同的 classes/functions 或任何东西?内存不是问题,我只对速度感兴趣
不要将数据复制到新的缓冲区对象中。直接从ios缓冲区读取。
byte type = ios.get();
switch (type) {
case 3:
return ios.getLong();
}
ByteBuffer中的所有getter都会根据数据类型的长度增加position。 get()将位置加1,getLong()加8,getFloat()加4……直接用ios.getLong()就可以了。假设值是一个接一个写入的,新位置将指向下一个类型字节。所以可以直接调用ios.get()得到下一个类型
编辑:
如果ios 是一个InputStream,您可以使用DataInputStream 来读取。它还支持各种数据类型。
DataInputStream input = new DataInputStream(ios);
byte type = input.readByte();
switch (type) {
case 3:
return input.readLong();
}
在 Java 中,基本上有两个包提供您正在寻找的功能。 java.io 和 java.nio。 java.io 包含流,而 java.nio 包含缓冲区。 java.nio 更快,因为它使用非常低级的内存操作。如果您正在寻找速度,则应该使用它。这也意味着您应该尽可能将 ios 的类型更改为 ByteBuffer,然后使用我的第一种方法。