Obtém a matriz de bytes de um ByteBuffer em java

94

Esta é a maneira recomendada de obter os bytes do ByteBuffer

ByteBuffer bb =..

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

Respostas:

107

Depende do que você quer fazer.

Se o que você quer é recuperar os bytes restantes (entre a posição e o limite), então o que você tem vai funcionar. Você também pode simplesmente fazer:

ByteBuffer bb =..

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

que é equivalente de acordo com os javadocs ByteBuffer .

Jason S
fonte
6
Corrigir. E observe que bb.capacity() pode ser igual bb.remaining()mesmo quando a matriz de apoio é mais longa, portanto, você não deve usar sua igualdade como um teste de quando bb.array()está correto. Veja ByteBuffer.slice().
cdunn2001
1
Observe que, para evitar alterar a posição do buffer, usei bb.slice().remaining(). Dessa forma, parece um dump limpo sem tocar no buffer original.
Kyll
este método me dá bytes assinados no entanto eu quero não assinados ... alguma idéia?
H Raval
Java não tem a noção de inteiros sem sinal, apenas assinados. Se você quiser "bytes não assinados", você precisa lançar como inte usar uma máscara de bits: int unsigned_byte = b[k] & 0xff;para algum valor de k.
Jason S,
Se você quiser colocar o buffer inteiro em uma matriz de bytes, você chamaria ByteBuffer#clearprimeiro?
Kenny Worden
21

Observe que bb.array () não respeita a posição dos buffers de bytes e pode ser ainda pior se o bytebuffer em que você está trabalhando for uma fatia de algum outro buffer.

Ie

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"

O que pode não ser o que você pretende fazer.

Se você realmente não deseja copiar o byte-array, uma solução alternativa pode ser usar o arrayOffset () + restante () do buffer de bytes, mas isso só funciona se o aplicativo suportar índice + comprimento dos buffers de bytes necessidades.

R4zorax
fonte
"bb.array () não respeita a posição dos buffers de bytes", você pode nos fornecer mais detalhes sobre esta parte. Eu entendi o exemplo do slice, mas preciso de mais detalhes sobre por que bb.array () bagunça
kkrishnaai
5

Tão simples como isso

  private static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
    byte[] bytesArray = new byte[byteBuffer.remaining()];
    byteBuffer.get(bytesArray, 0, bytesArray.length);
    return bytesArray;
}
Salman Nazir
fonte
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
Jin Kwon
fonte
4

Se alguém não souber nada sobre o estado interno do ByteBuffer (direto) fornecido e quiser recuperar todo o conteúdo do buffer, isso pode ser usado:

ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);
Tomáš Myšík
fonte
ByteBuffer.get(byte[])retorna aByteBuffer
pyb
E...? Não tenho certeza do que você quer dizer, desculpe.
Tomáš Myšík
A questão é como passar de um ByteBuffer para um byte [].
pyb 01 de
2
Uma vez chamados, eles estão na datavariável. O getter retorna this, consulte seu Javadoc.
Tomáš Myšík
Obrigado, não entendi. Como o método get está retornando um valor, eu não esperava que tivesse um efeito colateral também.
pyb 01 de
1

Esta é uma maneira simples de obter um byte [], mas parte do objetivo de usar um ByteBuffer é evitar a criação de um byte []. Talvez você possa obter o que deseja obter do byte [] diretamente do ByteBuffer.

Peter Lawrey
fonte
15
Mas frequentemente você precisará chamar algo (não em seu próprio código) que leva um byte [], então a conversão não é opcional.
James Moore,