Ricerca…


introduzione

La classe ByteBuffer è stata introdotta in java 1.4 per facilitare il lavoro sui dati binari. È particolarmente adatto per l'uso con dati di tipo primitivi. Permette la creazione, ma anche la successiva manipolazione di un byte[] s su un livello di astrazione più alto

Sintassi

  • byte [] arr = new byte [1000];
  • ByteBuffer buffer = ByteBuffer.wrap (arr);
  • ByteBuffer buffer = ByteBuffer.allocate (1024);
  • ByteBuffer buffer = ByteBuffer.allocateDirect (1024);
  • byte b = buffer.get ();
  • byte b = buffer.get (10);
  • short s = buffer.getShort (10);
  • buffer.put ((byte) 120);
  • buffer.putChar ( 'a');

Utilizzo di base - Creazione di un ByteBuffer

Esistono due modi per creare un ByteBuffer , in cui è possibile suddividerlo nuovamente.

Se hai un byte[] già esistente byte[] , puoi "racchiuderlo" in un ByteBuffer per semplificare l'elaborazione:

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

Questa sarebbe una possibilità per il codice che gestisce le interazioni di rete di basso livello


Se non si dispone di un byte[] già esistente byte[] , è possibile creare un ByteBuffer su un array specificamente assegnato per il buffer in questo modo:

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

Se il percorso del codice è estremamente critico per le prestazioni ed è necessario l'accesso diretto alla memoria di sistema , ByteBuffer può anche allocare buffer diretti usando #allocateDirect()

Utilizzo di base: scrittura dei dati nel buffer

Data un'istanza ByteBuffer possibile scrivere dati di tipo primitivo usando la put relativa e assoluta . La sorprendente differenza è che mettendo i dati usando il metodo relativo si tiene traccia dell'indice in cui i dati sono inseriti, mentre il metodo assoluto richiede sempre un indice per put i dati.

Entrambi i metodi consentono chiamate "concatenate" . Dato un buffer sufficientemente grande, si può fare quanto segue:

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

che è equivalente a:

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

Si noti che il metodo operativo su byte s non è denominato appositamente. Nota inoltre che è anche valido per passare sia un ByteBuffer sia un byte[] da put . Oltre a questo, tutti i tipi primitivi hanno metodi di put specializzati.

Una nota aggiuntiva: l'indice dato quando si usa la put* assoluta put* viene sempre conteggiato in byte s.

Utilizzo di base: utilizzo di DirectByteBuffer

DirectByteBuffer è un'implementazione speciale di ByteBuffer che non ha byte[] posto sotto.

Possiamo assegnare tale ByteBuffer chiamando:

ByteBuffer directBuffer = ByteBuffer.allocateDirect(16);

Questa operazione alloca 16 byte di memoria. Il contenuto dei buffer diretti può risiedere al di fuori del normale heap spazzato.

Possiamo verificare se ByteBuffer è diretto chiamando:

directBuffer.isDirect(); // true

Le caratteristiche principali di DirectByteBuffer è che JVM proverà a lavorare in modo nativo sulla memoria allocata senza alcun buffer aggiuntivo, in modo che le operazioni eseguite su di esso possano essere più veloci di quelle eseguite su ByteBuffer con array sottostanti.

Si consiglia di utilizzare DirectByteBuffer con pesanti operazioni IO che si basano sulla velocità di esecuzione, come la comunicazione in tempo reale.

Dobbiamo essere consapevoli che se proviamo ad usare il metodo array() otterremo UnsupportedOperationException . Quindi è una buona pratica per controllare se il nostro ByteBuffer lo ha (array di byte) prima di provare ad accedervi:

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

Un altro uso del buffer di byte diretto è l'interoperabilità con JNI. Poiché un buffer di byte diretto non usa un byte[] , ma un effettivo blocco di memoria, è possibile accedere a quella memoria direttamente tramite un puntatore nel codice nativo. Ciò può far risparmiare un po 'di problemi e sovraccarico sul marshalling tra la rappresentazione Java e nativa dei dati.

L'interfaccia JNI definisce diverse funzioni per gestire i buffer di byte diretti: supporto NIO .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow