从Java中的ByteBuffer获取字节数组


94

这是从ByteBuffer获取字节的推荐方法吗

ByteBuffer bb =..

byte[] b = new byte[bb.remaining()]
bb.get(b, 0, b.length);

Answers:


107

取决于您要做什么。

如果您要检索的是剩余字节(在位置和限制之间),那么您所拥有的将起作用。您也可以这样做:

ByteBuffer bb =..

byte[] b = new byte[bb.remaining()];
bb.get(b);

根据ByteBuffer javadocs 等效。


6
正确。并且请注意,即使支持数组更长,该值bb.capacity() 也可能相等bb.remaining(),因此您不得使用它们的相等性作为对何时bb.array()正确的检验。请参阅ByteBuffer.slice()
cdunn2001

1
请注意,为避免更改缓冲区的位置,我使用了bb.slice().remaining()。这样一来,它看上去就像是一个干净的转储,而没有触及原始缓冲区。
Kyll

这种方法给了我带符号的字节,但是我想要无符号的...任何想法吗?
H拉瓦尔

Java没有无符号整数的概念,只有带符号的整数。如果您想使用“无符号字节”,则需要将强制转换为,int并使用bitmask:int unsigned_byte = b[k] & 0xff;的某个值k
杰森S

如果要将整个缓冲区放入一个字节数组中,请先调用ByteBuffer#clear吗?
肯尼·沃登,

21

请注意,bb.array()不支持字节缓冲区的位置,如果正在处理的字节缓冲区是其他缓冲区的一部分,则可能会更糟。

byte[] test = "Hello World".getBytes("Latin1");
ByteBuffer b1 = ByteBuffer.wrap(test);
byte[] hello = new byte[6];
b1.get(hello); // "Hello "
ByteBuffer b2 = b1.slice(); // position = 0, string = "World"
byte[] tooLong = b2.array(); // Will NOT be "World", but will be "Hello World".
byte[] world = new byte[5];
b2.get(world); // world = "World"

您可能不想这样做。

如果您确实不想复制字节数组,则可以使用字节缓冲区的arrayOffset()+剩余的()解决方法,但这仅在应用程序支持字节缓冲区的index + length时才有效。需要。


“ bb.array()不遵守字节缓冲区的位置”,您能为我们提供有关此部分的更多详细信息吗?我理解了切片示例,但需要更多有关bb.array()为何混乱的详细信息
kkrishnaai

5

就如此容易

  private static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
    byte[] bytesArray = new byte[byteBuffer.remaining()];
    byteBuffer.get(bytesArray, 0, bytesArray.length);
    return bytesArray;
}

4
final ByteBuffer buffer;
if (buffer.hasArray()) {
    final byte[] array = buffer.array();
    final int arrayOffset = buffer.arrayOffset();
    return Arrays.copyOfRange(array, arrayOffset + buffer.position(),
                              arrayOffset + buffer.limit());
}
// do something else

4

如果一个人对给定的(Direct)ByteBuffer的内部状态一无所知,并且想要检索缓冲区的全部内容,则可以使用:

ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);

ByteBuffer.get(byte[])返回一个ByteBuffer
pyb '18

和...?不确定您的意思,对不起。
托马什Myšík

问题是如何从ByteBuffer变为byte []。
pyb

2
一旦调用,它们就在data变量中。getter返回this,请参见其Javadoc。
托马什Myšík

谢谢,我没明白。由于get方法返回一个值,所以我并不期望它也会产生副作用。
pyb

1

这是获取byte []的简单方法,但是使用ByteBuffer的部分目的是避免必须创建byte []。也许您可以直接从ByteBuffer中获得想要从byte []获得的任何内容。


15
但是通常您需要调用某些需要使用byte []的东西(而不是在自己的代码中),因此转换不是可选的。
James Moore
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.