Pobiera tablicę bajtów z ByteBuffer w java

96

Czy jest to zalecany sposób pobierania bajtów z ByteBuffer

ByteBuffer bb =..

byte[] b = new byte[bb.remaining()]
bb.get(b, 0, b.length);
kal
źródło

Odpowiedzi:

108

Zależy od tego, co chcesz zrobić.

Jeśli chcesz pobrać pozostałe bajty (między pozycją a limitem), wtedy to, co masz, zadziała. Możesz też po prostu zrobić:

ByteBuffer bb =..

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

co jest równoważne z javadocs ByteBuffer .

Jason S.
źródło
6
Poprawny. Zauważ, że bb.capacity() może się to równać bb.remaining()nawet wtedy, gdy tablica podstawowa jest dłuższa, więc nie możesz używać ich równości jako testu, kiedy bb.array()jest poprawna. Zobacz ByteBuffer.slice().
cdunn2001
1
Zwróć uwagę, że aby uniknąć zmiany położenia bufora, użyłem bb.slice().remaining(). W ten sposób wygląda jak czysty zrzut bez dotykania oryginalnego bufora.
Kyll
ta metoda daje mi podpisane bajty, ale chcę bez znaku ... jakiś pomysł?
H Raval
Java nie ma pojęcia liczb całkowitych bez znaku, tylko ze znakiem. Jeśli chcesz mieć „bajty bez znaku”, musisz rzutować jako inti użyć maski bitowej: int unsigned_byte = b[k] & 0xff;dla jakiejś wartości k.
Jason S
Jeśli chcesz pobrać cały bufor do tablicy bajtów, czy zadzwonisz ByteBuffer#clearnajpierw?
Kenny Worden
21

Zauważ, że bb.array () nie honoruje pozycji buforów bajtów i może być nawet gorsze, jeśli bufor bajtowy, nad którym pracujesz, jest fragmentem innego bufora.

To znaczy

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"

Co może nie być tym, co zamierzasz zrobić.

Jeśli naprawdę nie chcesz kopiować tablicy bajtów, rozwiązaniem może być użycie tablicy bufora bajtów () + pozostały (), ale działa to tylko wtedy, gdy aplikacja obsługuje indeks + długość buforów bajtów. wymagania.

R4zorax
źródło
„bb.array () nie honoruje pozycji buforów bajtów”, czy możesz podać nam więcej szczegółów na temat tej części. Zrozumiałem przykład plastra, ale potrzebuję więcej szczegółów na temat tego, dlaczego bb.array ()
zepsuło
5

Tak proste jak to

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

Jeśli nie wiemy nic o stanie wewnętrznym danego (bezpośredniego) ByteBuffera i chce się pobrać całą zawartość bufora, można to wykorzystać:

ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);
Tomáš Myšík
źródło
ByteBuffer.get(byte[])zwraca aByteBuffer
pyb
I...? Nie wiem, co masz na myśli, przepraszam.
Tomáš Myšík
Pytanie brzmi, jak przejść z ByteBuffer do bajtu [].
pyb
2
Raz wywołane są w datazmiennej. Getter powraca this, zobacz jego Javadoc.
Tomáš Myšík
Dzięki, nie rozumiem. Ponieważ metoda get zwraca wartość, nie spodziewałem się, że będzie miała również efekt uboczny.
pyb
1

Jest to prosty sposób na uzyskanie bajtu [], ale częścią zastosowania ByteBuffer jest uniknięcie konieczności tworzenia bajtu []. Być może możesz uzyskać wszystko, co chcesz, z bajtu [] bezpośrednio z ByteBuffer.

Peter Lawrey
źródło
15
Ale często będziesz musiał wywołać coś (nie we własnym kodzie), co zajmuje bajt [], więc konwersja nie jest opcjonalna.
James Moore,