1概要

この簡単な記事では、

java.nio

パッケージの


MappedByteBuffer


を見ていきます。このユーティリティは効率的なファイル読み込みに非常に役立ちます。


2どのように

__MappedByteBuffer W

__orks

ファイルの領域を読み込むときは、後でアクセスできる特定のメモリ領域に読み込むことができます。

ファイルの内容を複数回読み取る必要があることがわかった場合は、費用のかかるプロセスを最適化することをお勧めします。その内容をメモリに保存します。そのおかげで、ファイルのその部分のその後の検索は、ディスクからデータをロードする必要なしにメインメモリだけに行き、待ち時間を大幅に減らすことができます。


MappedByteBuffer

を使用するときに注意する必要があることの1つは、ディスクから非常に大きなファイルを扱う場合です –

ファイルがメモリに収まるようにする必要があります

そうでなければ、メモリ全体をいっぱいにして、結果として、共通の__OutOfMemoryExceptionに遭遇する可能性があります。


3

MappedByteBuffer


を使用したファイルの読み取り

次の内容を含む

fileToRead.txt

というファイルがあるとします。

This is a content of the file

ファイルは

/resource

ディレクトリにあるので、次の関数を使って読み込むことができます。

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

ファイルから

MappedByteBuffer

を作成するには、まずそのファイルから

FileChannel

を作成する必要があります。チャネルを作成したら、

MapMode、読み込み元の

position

、および必要なバイト数を指定する

size

パラメータを渡して、

map()__メソッドを呼び出すことができます。

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

ファイルをメモリマップバッファにマップしたら、そこから

CharBufferにデータを読み込むことができます。

ModepedByteBufferを渡して

decode()

メソッドを呼び出すときにファイルの内容を読み込んでいることに注意してください。ディスクからではなく、メモリから読み取ります。したがって、その読み取りは非常に高速になります。

ファイルから読み込んだコンテンツは、

fileToRead.txt

ファイルの実際のコンテンツであると言えるでしょう。

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

その後の

mappedByteBuffer

からの読み取りは非常に高速になります。これは、ファイルの内容がメモリーにマップされており、読み取りはディスクからデータを検索する必要なしに行われるためです。


4

MappedByteBuffer


を使用してファイルに書き込む


MappedByteBuffer

APIを使用して

fileToWriteTo.txt

ファイルにコンテンツを書き込みたいとしましょう。そのためには、

FileChannel

を開き、その上で

map()

メソッドを呼び出して

FileChannel.MapMode.READ

WRITE.__を渡す必要があります。

次に、

MappedByteBufferの

put()メソッドを使用して、

CharBuffer

の内容をファイルに保存します。

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


charBuffer

の実際の内容は、その内容を読み取ることでファイルに書き込まれたと主張できます。

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


5結論

このクイックチュートリアルでは、

java.nio

パッケージの

MappedByteBuffer

構造を見ていました。

ファイルはメモリにマップされ、その後の読み込みで毎回ディスクにアクセスする必要がないため、これはファイルの内容を複数回読み込むための非常に効率的な方法です。

これらすべての例とコードスニペットはhttps://github.com/eugenp/tutorials/tree/master/core-java-io[GitHubに追加]を見つけることができます – これはMavenプロジェクトです。そのまま実行します。