Поиск…


Вступление

Класс ByteBuffer был введен в java 1.4 для облегчения работы с двоичными данными. Он особенно подходит для использования с данными примитивного типа. Это позволяет создавать, но также и последующую манипуляцию byte[] s на более высоком уровне абстракции

Синтаксис

  • byte [] arr = новый байт [1000];
  • ByteBuffer buffer = ByteBuffer.wrap (arr);
  • ByteBuffer buffer = ByteBuffer.allocate (1024);
  • ByteBuffer buffer = ByteBuffer.allocateDirect (1024);
  • byte b = buffer.get ();
  • байт b = buffer.get (10);
  • short s = buffer.getShort (10);
  • buffer.put ((byte) 120);
  • buffer.putChar ( 'а');

Основное использование - создание ByteBuffer

Существует два способа создания ByteBuffer , где можно снова подразделить.

Если у вас уже есть byte[] , вы можете «обернуть» его в ByteBuffer чтобы упростить обработку:

byte[] reqBuffer = new byte[BUFFER_SIZE];
int readBytes = socketInputStream.read(reqBuffer);
final ByteBuffer reqBufferWrapper = ByteBuffer.wrap(reqBuffer);

Это будет возможность для кода, который обрабатывает сетевые взаимодействия на низком уровне


Если у вас нет уже существующего byte[] , вы можете создать ByteBuffer над массивом, специально выделенным для буфера следующим образом:

final ByteBuffer respBuffer = ByteBuffer.allocate(RESPONSE_BUFFER_SIZE);
putResponseData(respBuffer);
socketOutputStream.write(respBuffer.array());

Если код-путь чрезвычайно критичен по производительности и вам нужен прямой доступ к системной памяти , ByteBuffer может даже выделять прямые буферы с помощью #allocateDirect()

Основное использование - запись данных в буфер

Учитывая ByteBuffer экземпляр можно записывать данные примитивного типа к нему с помощью относительного и абсолютного put . Поразительное различие заключается в том, что помещение данных с использованием относительного метода отслеживает индекс, в который данные вставляются для вас, в то время как абсолютный метод всегда требует указания индекса для put данных.

Оба метода позволяют «цепочки» вызовов. При достаточно большом буфере можно сделать следующее:

buffer.putInt(0xCAFEBABE).putChar('c').putFloat(0.25).putLong(0xDEADBEEFCAFEBABE);

что эквивалентно:

buffer.putInt(0xCAFEBABE);
buffer.putChar('c');
buffer.putFloat(0.25);
buffer.putLong(0xDEADBEEFCAFEBABE);

Обратите внимание, что метод, базирующийся на byte не указан специально. Кроме того , обратите внимание , что это справедливо и для передачи одновременно ByteBuffer и byte[] , чтобы put . Кроме этого, все примитивные типы имеют специализированные put методы.

Дополнительная заметка: индекс, указанный при использовании абсолютного значения put* , всегда учитывается в byte .

Основное использование - использование DirectByteBuffer

DirectByteBuffer - это специальная реализация ByteBuffer , у которой нет byte[] .

Мы можем выделить такой ByteBuffer, вызывая:

ByteBuffer directBuffer = ByteBuffer.allocateDirect(16);

Эта операция будет выделять 16 байт памяти. Содержимое прямых буферов может находиться вне обычной кучи мусора.

Мы можем проверить, является ли ByteBuffer прямым, вызывая:

directBuffer.isDirect(); // true

Основные характеристики DirectByteBuffer том, что JVM будет пытаться изначально работать с выделенной памятью без дополнительной буферизации, поэтому выполняемые на ней операции могут быть быстрее, чем выполняемые на ByteBuffers с лежащими под ним массивами.

Рекомендуется использовать DirectByteBuffer с тяжелыми операциями ввода-вывода, которые полагаются на скорость выполнения, например, в режиме реального времени.

Мы должны знать, что если мы попытаемся использовать метод array() мы получим UnsupportedOperationException . Таким образом, это хорошая практика, чтобы проверить, есть ли у нашего ByteBuffer (байтовый массив), прежде чем мы попытаемся получить к нему доступ:

 byte[] arrayOfBytes;
 if(buffer.hasArray()) {
     arrayOfBytes = buffer.array();
 }

Другое использование прямого байтового буфера - это взаимодействие через JNI. Поскольку буфер прямого байта не использует byte[] , а представляет собой фактический блок памяти, можно получить доступ к этой памяти непосредственно через указатель в собственном коде. Это может сэкономить массу проблем и накладных расходов при сортировке между Java и собственным представлением данных.

Интерфейс JNI определяет несколько функций для обработки буферов с прямым байтом: поддержка NIO .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow