Verwenden von Java MappedByteBuffer

1. Übersicht

In diesem kurzen Artikel sehen wir uns den MappedByteBuffer im Paket java.nio an. Dieses Dienstprogramm kann für effizientes Lesen von Dateien sehr nützlich sein.

2. Wie MappedByteBuffer arbeitet

Wenn wir einen Bereich der Datei laden, können wir ihn in den bestimmten Speicherbereich laden, auf den später zugegriffen werden kann.

Wenn wir wissen, dass wir den Inhalt einer Datei mehrmals lesen müssen, ist es eine gute Idee, den kostspieligen Prozess zu optimieren, z. B. indem Sie diesen Inhalt im Speicher speichern. Dank dessen werden nachfolgende Suchvorgänge für diesen Teil der Datei nur in den Hauptspeicher verschoben, ohne dass die Daten von der Disc geladen werden müssen, wodurch die Latenz erheblich reduziert wird.

Eine Sache, mit der wir vorsichtig sein müssen, wenn wir den MappedByteBuffer verwenden, ist, wenn wir mit sehr großen Dateien von der Disc arbeiten - wir müssen sicherstellen, dass die Datei in den Speicher passt .

Andernfalls können wir den gesamten Speicher füllen und infolgedessen auf die gemeinsame OutOfMemoryException stoßen. Wir können dies überwinden, indem wir nur einen Teil der Datei laden - beispielsweise basierend auf Verwendungsmustern.

3. Lesen der Datei mit MappedByteBuffer

Angenommen , wir haben eine Datei namens fileToRead.txt mit folgendem Inhalt:

This is a content of the file

Die Datei befindet sich im Verzeichnis / resource, sodass wir sie mit der folgenden Funktion laden können:

Path getFileURIFromResources(String fileName) throws Exception { ClassLoader classLoader = getClass().getClassLoader(); return Paths.get(classLoader.getResource(fileName).getPath()); }

Um den MappedByteBuffer aus einer Datei zu erstellen, müssen wir zunächst einen FileChannel daraus erstellen . Sobald wir unseren Channel erstellt haben , können wir die aufrufen Karte () Methode auf es in dem Passieren Kartenmodus, eine Position , aus der wir lesen wollen, und die Größe Parameter, der angibt , wie viele Bytes wir wollen:

CharBuffer charBuffer = null; Path pathToRead = getFileURIFromResources("fileToRead.txt"); try (FileChannel fileChannel (FileChannel) Files.newByteChannel( pathToRead, EnumSet.of(StandardOpenOption.READ))) { MappedByteBuffer mappedByteBuffer = fileChannel .map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()); if (mappedByteBuffer != null) { charBuffer = Charset.forName("UTF-8").decode(mappedByteBuffer); } }

Sobald wir unsere Datei dem Speicherzuordnungspuffer zugeordnet haben, können wir die Daten daraus in den CharBuffer lesen. Es ist wichtig zu beachten, dass wir zwar den Inhalt der Datei lesen, wenn wir die decode () -Methode aufrufen, die MappedByteBuffer übergibt, aber aus dem Speicher und nicht von der Disc lesen. Daher wird das Lesen sehr schnell sein.

Wir können behaupten, dass der Inhalt, den wir aus unserer Datei lesen, der tatsächliche Inhalt der Datei fileToRead.txt ist:

assertNotNull(charBuffer); assertEquals( charBuffer.toString(), "This is a content of the file");

Jeder nachfolgende Lesevorgang aus dem mappedByteBuffer ist sehr schnell, da der Inhalt der Datei im Speicher zugeordnet ist und das Lesen erfolgt, ohne dass Daten von der Disc gesucht werden müssen.

4. Schreiben mit MappedByteBuffer in die Datei

Angenommen , wir möchten mithilfe der MappedByteBuffer- API Inhalte in die Datei fileToWriteTo.txt schreiben . Um dies zu erreichen, müssen wir den FileChannel öffnen und die map () -Methode darauf aufrufen , wobei wir FileChannel.MapMode.READ_WRITE übergeben.

Als nächstes können wir den Inhalt des CharBuffers mit der put () -Methode aus dem MappedByteBuffer in der Datei speichern:

CharBuffer charBuffer = CharBuffer .wrap("This will be written to the file"); Path pathToWrite = getFileURIFromResources("fileToWriteTo.txt"); try (FileChannel fileChannel = (FileChannel) Files .newByteChannel(pathToWrite, EnumSet.of( StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING))) { MappedByteBuffer mappedByteBuffer = fileChannel .map(FileChannel.MapMode.READ_WRITE, 0, charBuffer.length()); if (mappedByteBuffer != null) { mappedByteBuffer.put( Charset.forName("utf-8").encode(charBuffer)); } }

Wir können behaupten, dass der tatsächliche Inhalt des charBuffer in die Datei geschrieben wurde, indem wir den Inhalt lesen:

List fileContent = Files.readAllLines(pathToWrite); assertEquals(fileContent.get(0), "This will be written to the file");

5. Schlussfolgerung

In diesem kurzen Tutorial haben wir uns das MappedByteBuffer- Konstrukt aus dem Paket java.nio angesehen .

Dies ist eine sehr effiziente Methode, um den Inhalt der Datei mehrmals zu lesen, da die Datei dem Speicher zugeordnet ist und nachfolgende Lesevorgänge nicht jedes Mal auf die Disc gehen müssen.

Alle diese Beispiele und Codefragmente finden Sie auf GitHub - dies ist ein Maven-Projekt, daher sollte es einfach zu importieren und auszuführen sein.