Obtient un tableau d'octets à partir d'un ByteBuffer en java

95

Est-ce la méthode recommandée pour obtenir les octets du ByteBuffer

ByteBuffer bb =..

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

Réponses:

107

Ça dépend de ce que tu veux faire.

Si vous voulez récupérer les octets restants (entre la position et la limite), alors ce que vous avez fonctionnera. Vous pouvez aussi simplement faire:

ByteBuffer bb =..

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

qui est équivalent selon les javadocs ByteBuffer.

Jason S
la source
6
Correct. Et notez que cela bb.capacity() peut être égal bb.remaining()même lorsque le tableau de sauvegarde est plus long, vous ne devez donc pas utiliser leur égalité comme un test de quand bb.array()est correct. Voir ByteBuffer.slice().
cdunn2001
1
Notez que, pour éviter de changer la position du tampon, j'ai utilisé bb.slice().remaining(). De cette façon, cela ressemble à un vidage propre sans toucher le tampon d'origine.
Kyll
cette méthode me donne des octets signés mais je veux non signés ... une idée?
H Raval
Java n'a pas la notion d'entiers non signés, seulement ceux signés. Si vous voulez des "octets non signés", vous devez effectuer un cast intet utiliser un masque de bits: int unsigned_byte = b[k] & 0xff;pour une valeur de k.
Jason S
Si vous voulez obtenir le tampon entier dans un tableau d'octets, appelez-vous en ByteBuffer#clearpremier?
Kenny Worden
21

Notez que bb.array () n'honore pas la position des byte-buffers, et pourrait être encore pire si le bytebuffer sur lequel vous travaillez est une tranche d'un autre tampon.

C'est à dire

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"

Ce n'est peut-être pas ce que vous avez l'intention de faire.

Si vous ne voulez vraiment pas copier le tableau d'octets, une solution de contournement pourrait être d'utiliser le arrayOffset () + restant () du tampon d'octets, mais cela ne fonctionne que si l'application prend en charge l'index + la longueur des tampons d'octets. Besoins.

R4zorax
la source
"bb.array () n'honore pas la position des byte-buffers", pouvez-vous nous fournir plus de détails sur cette partie. J'ai compris l'exemple de la tranche mais j'ai besoin de plus de détails sur les raisons pour lesquelles bb.array ()
gâche
5

Aussi simple que cela

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

Si l'on ne sait rien de l'état interne du ByteBuffer (Direct) donné et veut récupérer tout le contenu du buffer, on peut l'utiliser:

ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);
Tomáš Myšík
la source
ByteBuffer.get(byte[])renvoie aByteBuffer
pyb
Et...? Je ne sais pas ce que tu veux dire, désolé.
Tomáš Myšík
La question est de savoir comment passer d'un ByteBuffer à un byte [].
pyb
2
Une fois appelés, ils sont dans la datavariable. Le getter revient this, voir son Javadoc.
Tomáš Myšík
Merci, je n'ai pas compris. Étant donné que la méthode get renvoie une valeur, je ne m'attendais pas à ce qu'elle ait également un effet secondaire.
pyb
1

C'est un moyen simple d'obtenir un octet [], mais une partie du but d'utiliser un ByteBuffer est d'éviter d'avoir à créer un octet []. Peut-être pouvez-vous obtenir tout ce que vous vouliez obtenir de l'octet [] directement du ByteBuffer.

Peter Lawrey
la source
15
Mais souvent vous aurez besoin d'appeler quelque chose (pas dans votre propre code) qui prend un octet [], donc la conversion n'est pas facultative.
James Moore