Obtiene una matriz de bytes de un ByteBuffer en java

96

¿Es esta la forma recomendada de obtener los bytes del ByteBuffer?

ByteBuffer bb =..

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

Respuestas:

108

depende de lo que quieras hacer.

Si lo que quieres es recuperar los bytes que quedan (entre posición y límite), entonces lo que tienes funcionará. También puedes hacer:

ByteBuffer bb =..

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

que es equivalente según los javadocs ByteBuffer .

Jason S
fuente
6
Correcto. Y tenga en cuenta que bb.capacity() podría ser igual bb.remaining()incluso cuando la matriz de respaldo sea más larga, por lo que no debe usar su igualdad como una prueba de cuándo bb.array()es correcta. Ver ByteBuffer.slice().
cdunn2001
1
Tenga en cuenta que, para evitar cambiar la posición del búfer, utilicé bb.slice().remaining(). De esa manera, parece un vertedero limpio sin tocar el búfer original.
Kyll
este método me da bytes firmados sin embargo quiero sin firmar ... ¿alguna idea?
H Raval
Java no tiene la noción de enteros sin firmar, solo los firmados. Si desea "bytes sin firmar", debe convertir como inty usar una máscara de bits: int unsigned_byte = b[k] & 0xff;para algún valor de k.
Jason S
Si desea obtener todo el búfer en una matriz de bytes, ¿llamaría ByteBuffer#clearprimero?
Kenny Worden
21

Tenga en cuenta que bb.array () no respeta la posición de los búferes de bytes y podría ser incluso peor si el búfer de bytes en el que está trabajando es una porción de algún otro búfer.

Es decir

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"

Lo cual podría no ser lo que pretendes hacer.

Si realmente no desea copiar la matriz de bytes, una solución podría ser usar la matrizOffset () + restante () del búfer de bytes, pero esto solo funciona si la aplicación admite índice + longitud de los búferes de bytes necesidades.

R4zorax
fuente
"bb.array () no respeta la posición de los búferes de bytes", ¿puede proporcionarnos más detalles sobre esta parte? Entendí el ejemplo de corte pero necesito más detalles sobre por qué bb.array () se
equivoca
5

Tan sencillo como eso

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

Si uno no sabe nada sobre el estado interno del ByteBuffer (Directo) dado y desea recuperar todo el contenido del búfer, se puede utilizar:

ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);
Tomáš Myšík
fuente
ByteBuffer.get(byte[])devuelve aByteBuffer
pyb
Y...? No estoy seguro de lo que quieres decir, lo siento.
Tomáš Myšík
La cuestión es cómo pasar de un ByteBuffer a un byte [].
Pyb
2
Una vez llamados, están en la datavariable. El captador regresa this, vea su Javadoc.
Tomáš Myšík
Gracias, no entendí eso. Dado que el método get devuelve un valor, no esperaba que también tuviera un efecto secundario.
Pyb
1

Esta es una forma sencilla de obtener un byte [], pero parte del objetivo de usar un ByteBuffer es evitar tener que crear un byte []. Quizás pueda obtener lo que quiera obtener del byte [] directamente del ByteBuffer.

Peter Lawrey
fuente
15
Pero a menudo necesitará llamar a algo (no en su propio código) que tome un byte [], por lo que la conversión no es opcional.
James Moore