Java MappedByteBuffer verwenden

Verwenden von JavaMappedByteBuffer

1. Überblick

In diesem kurzen Artikel werden wir uns dieMappedByteBuffer imjava.nio-Paket ansehen. Dieses Dienstprogramm kann sehr nützlich sein, um Dateien effizient zu lesen.

2. WieMappedByteBuffer Works

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. durch Speichern dieses Inhalts im Speicher. Dank dessen werden nachfolgende Suchvorgänge für diesen Teil der Datei nur in den Hauptspeicher übertragen, ohne dass die Daten von der Disc geladen werden müssen, wodurch die Latenz erheblich verringert wird.

Eine Sache, mit der wir vorsichtig sein müssen, wenn wirMappedByteBuffer verwenden, ist, wenn wir mit sehr großen Dateien von Disc -we need to make sure the file will fit in memory arbeiten.

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

3. Lesen der Datei mitMappedByteBuffer

Nehmen wir an, wir haben eine Datei namensfileToRead.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 dieMappedByteBuffer aus einer Datei zu erstellen, müssen wir zuerst eineFileChannel daraus erstellen. Sobald wir unseren Kanal erstellt haben, können wir die Methodemap() aufrufen, indem wir dieMapMode,aposition übergeben, aus denen wir lesen möchten, und den Parametersize, der angibt, wie viele Bytes wollen wir:

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 in den Speicherzuordnungspuffer abgebildet haben, können wir die Daten daraus inCharBuffer. lesen. Es ist wichtig zu beachten, dass wir den Inhalt der Datei lesen, wenn wir diedecode()-Methode aufrufen, die übergeben wird MappedByteBuffer, lesen wir aus dem Speicher, nicht von der Disc. Daher ist das Lesen sehr schnell.

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

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

Jeder nachfolgende Lesevorgang vonmappedByteBuffer 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 in die Datei mitMappedByteBuffer

Angenommen, wir möchten mithilfe der APIMappedByteBuffer Inhalte in die DateifileToWriteTo.txt schreiben. Um dies zu erreichen, müssen wir dieFileChannel öffnen und diemap()-Methode darauf aufrufen, wobei wir dieFileChannel.MapMode.READ_WRITE. übergeben

Als nächstes können wir den Inhalt derCharBuffer mit derput()-Methode aus denMappedByteBuffer: 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 voncharBuffer 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. Fazit

In diesem kurzen Tutorial haben wir uns das KonstruktMappedByteBufferaus dem Paketjava.nioangesehen.

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

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