Java Language
ByteBuffer
Szukaj…
Wprowadzenie
Klasa ByteBuffer
została wprowadzona w Javie 1.4, aby ułatwić pracę na danych binarnych. Jest szczególnie odpowiedni do użycia z danymi typu pierwotnego. Umożliwia tworzenie, ale także późniejsze manipulowanie byte[]
na wyższym poziomie abstrakcji
Składnia
- byte [] arr = nowy bajt [1000];
- ByteBuffer buffer = ByteBuffer.wrap (arr);
- ByteBuffer buffer = ByteBuffer.allocate (1024);
- ByteBuffer buffer = ByteBuffer.allocateDirect (1024);
- bajt b = buffer.get ();
- bajt b = buffer.get (10);
- short s = buffer.getShort (10);
- buffer.put ((byte) 120);
- buffer.putChar („a”);
Podstawowe użycie - tworzenie ByteBuffer
Istnieją dwa sposoby utworzenia ByteBuffer
, w którym można ponownie podzielić.
Jeśli masz już byte[]
, możesz go „owinąć” w ByteBuffer
aby uprościć przetwarzanie:
byte[] reqBuffer = new byte[BUFFER_SIZE];
int readBytes = socketInputStream.read(reqBuffer);
final ByteBuffer reqBufferWrapper = ByteBuffer.wrap(reqBuffer);
To byłaby możliwość dla kodu, który obsługuje interakcje sieciowe niskiego poziomu
Jeśli nie masz jeszcze byte[]
, możesz utworzyć ByteBuffer
na tablicy specjalnie przypisanej do bufora, jak poniżej:
final ByteBuffer respBuffer = ByteBuffer.allocate(RESPONSE_BUFFER_SIZE);
putResponseData(respBuffer);
socketOutputStream.write(respBuffer.array());
Jeśli ścieżka kodu ma ogromne znaczenie dla wydajności i potrzebujesz bezpośredniego dostępu do pamięci systemowej , ByteBuffer
może nawet przydzielić bezpośrednie bufory za pomocą #allocateDirect()
Podstawowe użycie - zapis danych do bufora
Biorąc pod uwagę ByteBuffer
instancji można zapisywać dane prymitywne typu do niego przy użyciu względnej i bezwzględnej put
. Uderzająca różnica polega na tym, że umieszczanie danych przy użyciu metody względnej śledzi indeks, w którym dane są wstawiane, podczas gdy metoda bezwzględna zawsze wymaga podania indeksu, w którym put
są dane.
Obie metody umożliwiają połączenia „łańcuchowe” . Biorąc pod uwagę bufor o wystarczającej wielkości, można odpowiednio wykonać następujące czynności:
buffer.putInt(0xCAFEBABE).putChar('c').putFloat(0.25).putLong(0xDEADBEEFCAFEBABE);
co jest równoważne z:
buffer.putInt(0xCAFEBABE);
buffer.putChar('c');
buffer.putFloat(0.25);
buffer.putLong(0xDEADBEEFCAFEBABE);
Zauważ, że metoda działająca na byte
nie jest specjalnie nazwana. Dodatkowo zauważ, że prawidłowe jest również przekazanie ByteBuffer
i byte[]
do put
. Poza tym wszystkie pierwotne typy mają wyspecjalizowane metody put
.
Dodatkowa uwaga: Indeks podany przy stosowaniu wartości bezwzględnej put*
jest zawsze liczony w byte
.
Podstawowe użycie - korzystanie z DirectByteBuffer
DirectByteBuffer
to specjalna implementacja ByteBuffer
którą nie ma byte[]
.
Możemy przydzielić taki ByteBuffer, dzwoniąc:
ByteBuffer directBuffer = ByteBuffer.allocateDirect(16);
Ta operacja przydzieli 16 bajtów pamięci. Zawartość bezpośrednich buforów może znajdować się poza zwykłą stertą śmieci.
Możemy sprawdzić, czy ByteBuffer jest bezpośredni, dzwoniąc:
directBuffer.isDirect(); // true
Główną cechą DirectByteBuffer
jest to, że JVM spróbuje natywnie pracować na przydzielonej pamięci bez żadnego dodatkowego buforowania, więc operacje na nim wykonywane mogą być szybsze niż te wykonywane na ByteBuffers z tablicami leżącymi pod spodem.
Zaleca się stosowanie DirectByteBuffer
przypadku ciężkich operacji IO, które polegają na szybkości wykonania, np. Komunikacji w czasie rzeczywistym.
Musimy mieć świadomość, że jeśli spróbujemy użyć metody array()
, otrzymamy UnsupportedOperationException
. Dobrą praktyką jest sprawdzanie, czy nasz ByteBuffer go ma (tablica bajtów), zanim spróbujemy uzyskać do niego dostęp:
byte[] arrayOfBytes;
if(buffer.hasArray()) {
arrayOfBytes = buffer.array();
}
Innym zastosowaniem bufora bezpośrednich bajtów jest interop przez JNI. Ponieważ bufor bezpośrednich bajtów nie korzysta z byte[]
, lecz z rzeczywistego bloku pamięci, możliwe jest uzyskanie dostępu do tej pamięci bezpośrednio za pomocą wskaźnika w kodzie natywnym. Może to zaoszczędzić trochę kłopotów i narzutów podczas zestawiania między Javą a natywną reprezentacją danych.
Interfejs JNI definiuje kilka funkcji do obsługi bezpośrednich buforów bajtów: Obsługa NIO .