Java >> Java tutorial >  >> Tag >> byte

Brug af Java MappedByteBuffer

1. Oversigt

I denne hurtige artikel vil vi se på MappedByteBuffer i java.nio pakke. Dette værktøj kan være ret nyttigt til effektiv fillæsning.

2. Hvordan MappedByteBuffer W orks

Når vi indlæser en region af filen, kan vi indlæse den til den bestemte hukommelsesregion, der kan tilgås senere.

Når vi ved, at vi skal læse indholdet af en fil flere gange, er det en god idé at optimere den kostbare proces, f.eks. ved at gemme indholdet i hukommelsen. Takket være det vil efterfølgende opslag af den del af filen kun gå til hovedhukommelsen uden behov for at indlæse dataene fra disken, hvilket reducerer latenstiden væsentligt.

En ting, som vi skal være forsigtige med, når vi bruger MappedByteBuffer er, når vi arbejder med meget store filer fra disken – vi skal sikre, at filen passer i hukommelsen .

Ellers kan vi fylde hele hukommelsen og som en konsekvens løbe ind i den almindelige OutOfMemoryException. Det kan vi overvinde ved kun at indlæse en del af filen – baseret for eksempel på brugsmønstre.

3. Læsning af filen ved hjælp af MappedByteBuffer

Lad os sige, at vi har en fil kaldet fileToRead.txt med følgende indhold:

This is a content of the file

Filen er placeret i /ressource mappe, så vi kan indlæse den ved hjælp af følgende funktion:

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

For at oprette MappedByteBuffer fra en fil, skal vi først oprette en FileChannel fra det. Når vi har oprettet vores kanal, kan vi kalde map() metode på det, der passerer i MapMode, en stilling hvorfra vi ønsker at læse, og størrelsen parameter, der angiver hvor mange bytes vi ønsker:

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

Når vi har kortlagt vores fil i den hukommelseskortlagte buffer, kan vi læse dataene fra den ind i CharBufferen. Vigtigt at bemærke er, at selvom vi læser indholdet af filen, når vi kalder decode() metode, der sender MappedByteBuffer, vi læser fra hukommelsen, ikke fra disken. Derfor vil læsningen være meget hurtig.

Vi kan hævde, at indhold, som vi læser fra vores fil, er det faktiske indhold af fileToRead.txt fil:

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

Hver efterfølgende læsning fra mappedByteBuffer vil være meget hurtig, fordi indholdet af filen er kortlagt i hukommelsen og læsning sker uden behov for at slå data op fra disken.

4. Skrivning til filen ved hjælp af MappedByteBuffer

Lad os sige, at vi vil skrive noget indhold ind i filen fileToWriteTo.txt ved hjælp af MappedByteBuffer API. For at opnå det er vi nødt til at åbne FileChannel og kald map() metoden på det, der sender FileChannel.MapMode.READ_WRITE.

Dernæst kan vi gemme indholdet af CharBuffer ind i filen ved hjælp af put() metode fra MappedByteBuffer:

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

Vi kan hævde, at det faktiske indhold af charBuffer blev skrevet til filen ved at læse indholdet af den:

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

5. Konklusion

I denne hurtige vejledning kiggede vi på MappedByteBuffer konstruktion fra java.nio pakke.

Dette er en meget effektiv måde at læse indholdet af filen flere gange, da filen er mappet ind i hukommelsen og efterfølgende læsninger ikke behøver at gå til disk hver gang.

Alle disse eksempler og kodestykker kan findes på GitHub – dette er et Maven-projekt, så det burde være nemt at importere og køre som det er.


Java tag