Java Language
ByteBuffer
Zoeken…
Invoering
De ByteBuffer
klasse is geïntroduceerd in Java 1.4 om het werken aan binaire gegevens te vergemakkelijken. Het is met name geschikt voor gebruik met gegevens van het primitieve type. Hiermee kan een byte[]
s op een hoger abstractieniveau worden gemaakt, maar ook worden gemanipuleerd
Syntaxis
- byte [] arr = nieuwe 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);
- korte s = buffer.getShort (10);
- buffer.put ((byte) 120);
- buffer.putChar ( 'a');
Basisgebruik - Een ByteBuffer maken
Er zijn twee manieren om een ByteBuffer
te maken, waar u deze opnieuw kunt onderverdelen.
Als u al een bestaande byte[]
, kunt u deze in een ByteBuffer
"verpakken" om de verwerking te vereenvoudigen:
byte[] reqBuffer = new byte[BUFFER_SIZE];
int readBytes = socketInputStream.read(reqBuffer);
final ByteBuffer reqBufferWrapper = ByteBuffer.wrap(reqBuffer);
Dit zou een mogelijkheid zijn voor code die netwerkinteracties op laag niveau afhandelt
Als u nog geen bestaande byte[]
, kunt u een ByteBuffer
via een array die specifiek is toegewezen aan de buffer zoals deze:
final ByteBuffer respBuffer = ByteBuffer.allocate(RESPONSE_BUFFER_SIZE);
putResponseData(respBuffer);
socketOutputStream.write(respBuffer.array());
Als het ByteBuffer
zeer kritisch is voor de prestaties en u directe toegang tot het ByteBuffer
nodig hebt, kan de ByteBuffer
zelfs directe buffers toewijzen met #allocateDirect()
Basisgebruik - Schrijf gegevens naar de buffer
Gegeven een ByteBuffer
instantie kan men er gegevens van het primitieve type ByteBuffer
schrijven met behulp van relatieve en absolute put
. Het opvallende verschil is dat het plaatsen van gegevens met behulp van de relatieve methode de index bijhoudt waarin de gegevens voor u worden ingevoegd, terwijl de absolute methode altijd vereist dat een index wordt put
de gegevens op te put
.
Beide methoden maken "chaining" -oproepen mogelijk. Bij een voldoende grote buffer kan men dienovereenkomstig het volgende doen:
buffer.putInt(0xCAFEBABE).putChar('c').putFloat(0.25).putLong(0xDEADBEEFCAFEBABE);
wat overeenkomt met:
buffer.putInt(0xCAFEBABE);
buffer.putChar('c');
buffer.putFloat(0.25);
buffer.putLong(0xDEADBEEFCAFEBABE);
Houd er rekening mee dat de methode die werkt op byte
geen speciale naam heeft. Daarnaast is er rekening mee dat het is ook geldig voor zowel een passeren ByteBuffer
en een byte[]
om te put
. Anders dan dat, hebben alle primitieve typen gespecialiseerde put
methoden.
Een aanvullende opmerking: de index bij gebruik van absolute put*
wordt altijd geteld in byte
.
Basisgebruik - DirectByteBuffer gebruiken
DirectByteBuffer
is een speciale implementatie van ByteBuffer
waar geen byte[]
onder ligt.
We kunnen dergelijke ByteBuffer toewijzen door te bellen naar:
ByteBuffer directBuffer = ByteBuffer.allocateDirect(16);
Bij deze bewerking wordt 16 bytes geheugen toegewezen. De inhoud van directe buffers kan zich buiten de normale verzamelde hoop bevinden.
We kunnen verifiëren of ByteBuffer direct is door te bellen naar:
directBuffer.isDirect(); // true
De belangrijkste kenmerken van DirectByteBuffer
is dat JVM native aan toegewezen geheugen zal proberen te werken zonder extra buffering, zodat bewerkingen die erop worden uitgevoerd sneller kunnen zijn dan die uitgevoerd op ByteBuffers met arrays die eronder liggen.
Het wordt aanbevolen om DirectByteBuffer
te gebruiken met zware IO-bewerkingen die afhankelijk zijn van de snelheid van uitvoering, zoals realtime communicatie.
We moeten ons ervan bewust zijn dat als we de methode array()
proberen te gebruiken, we UnsupportedOperationException
krijgen. Het is dus een goede gewoonte om te controleren of onze ByteBuffer het heeft (byte array) voordat we proberen toegang te krijgen:
byte[] arrayOfBytes;
if(buffer.hasArray()) {
arrayOfBytes = buffer.array();
}
Een ander gebruik van directe byte buffer is interop via JNI. Aangezien een directe bytebuffer geen byte[]
, maar een daadwerkelijk geheugenblok, is het mogelijk om rechtstreeks toegang tot dat geheugen te krijgen via een pointer in native code. Dit kan een beetje moeite en overhead besparen bij het rangschikken tussen de Java en native weergave van gegevens.
De JNI-interface definieert verschillende functies voor het verwerken van directe byte-buffers: NIO Support .