Utilisation de Java MappedByteBuffer

Utilisation de JavaMappedByteBuffer

1. Vue d'ensemble

Dans cet article rapide, nous examinerons lesMappedByteBuffer du packagejava.nio. Cet utilitaire peut être très utile pour des lectures de fichiers efficaces.

2. CommentMappedByteBuffer Wfonctionne

Lorsque nous chargeons une région du fichier, nous pouvons la charger dans la région de mémoire particulière accessible ultérieurement.

Lorsque nous savons que nous aurons besoin de lire le contenu d'un fichier plusieurs fois, il est judicieux d'optimiser le processus coûteux, par exemple. en enregistrant ce contenu dans la mémoire. Grâce à cela, les recherches ultérieures de cette partie du fichier iront uniquement dans la mémoire principale sans qu'il soit nécessaire de charger les données à partir du disque, ce qui réduirait considérablement le temps de latence.

Une chose à laquelle nous devons faire attention lorsque vous utilisez lesMappedByteBuffer est lorsque nous travaillons avec de très gros fichiers à partir du disque -we need to make sure the file will fit in memory.

Sinon, nous pouvons remplir toute la mémoire et, par conséquent, nous heurter auxOutOfMemoryException. communs. Nous pouvons surmonter cela en ne chargeant qu'une partie du fichier - en fonction par exemple des modèles d'utilisation.

3. Lecture du fichier avecMappedByteBuffer

Disons que nous avons un fichier appeléfileToRead.txt avec le contenu suivant:

This is a content of the file

Le fichier se trouve dans le répertoire/resource afin que nous puissions le charger en utilisant la fonction suivante:

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

Pour créer lesMappedByteBuffer à partir d'un fichier, nous devons d'abord créer unFileChannel à partir de celui-ci. Une fois que nous avons créé notre canal, nous pouvons invoquer la méthodemap() dessus en passant lesMapMode,aposition à partir desquels nous voulons lire, et le paramètresize qui spécifie comment beaucoup d'octets que nous voulons:

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);
    }
}

Une fois que nous avons mappé notre fichier dans le tampon mappé en mémoire, nous pouvons lire les données de celui-ci dans leCharBuffer. Important à noter, bien que nous lisions le contenu du fichier lorsque nous appelons la méthodedecode() en passant MappedByteBuffer, que nous lisons depuis la mémoire, pas depuis le disque. Par conséquent, cette lecture sera très rapide.

Nous pouvons affirmer que le contenu que nous lisons dans notre fichier est le contenu réel du fichierfileToRead.txt:

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

Chaque lecture ultérieure à partir desmappedByteBuffer sera très rapide car le contenu du fichier est mappé en mémoire et la lecture se fait sans qu'il soit nécessaire de rechercher des données sur le disque.

4. Ecriture dans le fichier en utilisantMappedByteBuffer

Disons que nous voulons écrire du contenu dans le fichierfileToWriteTo.txt en utilisant l'APIMappedByteBuffer. Pour y parvenir, nous devons ouvrir leFileChannel et appeler la méthodemap() dessus, en passant leFileChannel.MapMode.READ_WRITE.

Ensuite, nous pouvons enregistrer le contenu desCharBuffer dans le fichier en utilisant la méthodeput() à partir desMappedByteBuffer:

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));
    }
}

Nous pouvons affirmer que le contenu réel descharBuffer a été écrit dans le fichier en lisant le contenu de celui-ci:

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

5. Conclusion

Dans ce rapide tutoriel, nous avons examiné la constructionMappedByteBuffer du packagejava.nio.

C'est un moyen très efficace de lire le contenu du fichier plusieurs fois, car le fichier est mappé en mémoire et les lectures suivantes n'ont pas besoin d'être enregistrées sur le disque à chaque fois.

Tous ces exemples et extraits de code peuvent être trouvésover on GitHub - il s'agit d'un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.