Отримує байтовий масив із ByteBuffer у Java


95

Це рекомендований спосіб отримати байти з ByteBuffer

ByteBuffer bb =..

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

Відповіді:


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 Raval

Java не має поняття цілих чисел без знака, лише підписані. Якщо ви хочете "непідписані байти", вам потрібно передати як intі використовувати бітову маску: int unsigned_byte = b[k] & 0xff;для деякого значення k.
Jason S,

Якщо ви хочете отримати весь буфер у байтовий масив, чи не зателефонуєте ви ByteBuffer#clearпершим?
Kenny Worden

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 () + залишився (), але це працює лише в тому випадку, якщо програма підтримує індекс + довжина байт-буферів потреби.


"bb.array () не відповідає позиції байтових буферів", чи можете ви надати нам більше інформації про цю частину. Я зрозумів приклад фрагмента, але мені потрібні додаткові відомості про те, чому bb.array ()
псує

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

Якщо хтось нічого не знає про внутрішній стан заданого (Прямого) ByteBuffer і хоче отримати весь вміст буфера, це можна використати:

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

ByteBuffer.get(byte[])повертає aByteBuffer
pyb

І ...? Не знаю, що ви маєте на увазі, вибачте.
Томаш Мишик,

Питання в тому, як перейти від ByteBuffer до байта [].
pyb

2
Після виклику вони потрапляють у dataзмінну. Геттер повертається this, див. Його Javadoc.
Томаш Мишик,

Дякую, я цього не зрозумів. Оскільки метод get повертає значення, я не очікував, що це також матиме побічний ефект.
pyb

1

Це простий спосіб отримати байт [], але частиною суті використання ByteBuffer є уникнення необхідності створювати байт []. Можливо, ви можете отримати все, що хотіли отримати з байта [], безпосередньо з ByteBuffer.


15
Але часто вам потрібно буде викликати щось (не у власному коді), яке займає байт [], тому перетворення не є необов’язковим.
Джеймс Мур,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.