広告

Java : MappedByteBuffer - API使用例

MappedByteBuffer (Java SE 22 & JDK 22) の使い方まとめです。
ほとんどのメソッドにサンプルコードがあります。
APIドキュメントのおともにどうぞ。


概要

ファイルのメモリー・マップ領域を内容とするダイレクトbyteバッファです。

クラス構成

MappedByteBuffer クラスは、ファイルと連動する ByteBuffer です。

API仕様にもありますが、プラットフォーム(Windows や Linux など) によって挙動が変わることがあるのでご注意ください。

public MappedByteBuffer createBuffer(Path file) throws IOException {
    try (final var channel = FileChannel.open(file,
            StandardOpenOption.READ, StandardOpenOption.WRITE)) {

        return channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
    }
}
final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

final var buffer = createBuffer(file);

{
    final var dst = new byte[buffer.capacity()];
    buffer.get(0, dst);
    System.out.println(Arrays.toString(dst)); // [10, 20, 30, 40, 50]

    final var ret = Files.readAllBytes(file);
    System.out.println(Arrays.toString(ret)); // [10, 20, 30, 40, 50]
}

buffer.put(0, (byte) -10);
buffer.put(1, (byte) -20);
buffer.put(2, (byte) -30);

{
    final var dst = new byte[buffer.capacity()];
    buffer.get(0, dst);
    System.out.println(Arrays.toString(dst)); // [-10, -20, -30, 40, 50]

    final var ret = Files.readAllBytes(file);
    System.out.println(Arrays.toString(ret)); // [-10, -20, -30, 40, 50]
}
final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file,
        StandardOpenOption.READ, StandardOpenOption.WRITE)) {

    final var buffer = channel.map(
            FileChannel.MapMode.READ_ONLY, 0, channel.size());

    {
        final var dst = new byte[buffer.capacity()];
        buffer.get(0, dst);
        System.out.println(Arrays.toString(dst)); // [10, 20, 30, 40, 50]

        final var ret = Files.readAllBytes(file);
        System.out.println(Arrays.toString(ret)); // [10, 20, 30, 40, 50]
    }

    final var src = ByteBuffer.allocate(3)
            .put((byte) -10)
            .put((byte) -20)
            .put((byte) -30)
            .clear();

    System.out.println(channel.write(src)); // 3

    {
        final var dst = new byte[buffer.capacity()];
        buffer.get(0, dst);
        System.out.println(Arrays.toString(dst)); // [-10, -20, -30, 40, 50]

        final var ret = Files.readAllBytes(file);
        System.out.println(Arrays.toString(ret)); // [-10, -20, -30, 40, 50]
    }
}

メソッド

final MappedByteBuffer clear ()

このバッファをクリアします。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    buffer.position(2);
    buffer.limit(4);

    System.out.println(buffer); // java.nio.DirectByteBufferR[pos=2 lim=4 cap=5]

    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.hasRemaining()); // false

    System.out.println(buffer.clear()); // java.nio.DirectByteBufferR[pos=0 lim=5 cap=5]

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.get()); // 20
    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.get()); // 50
    System.out.println(buffer.hasRemaining()); // false
}

abstract MappedByteBuffer compact ()

このバッファを圧縮します (オプションの操作)。

final var file = Path.of("R:", "java-work", "test1.data");
System.out.println(file); // R:\java-work\test1.data

final byte[] bytes = {10, 20, 30, 40, 50, 60};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file,
        StandardOpenOption.READ, StandardOpenOption.WRITE)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
    buffer.position(3);
    System.out.println(buffer.compact()); // java.nio.DirectByteBuffer[pos=3 lim=6 cap=6]
}

final var ret = Files.readAllBytes(file);
System.out.println(Arrays.toString(ret)); // [40, 50, 60, 40, 50, 60]
final var file = Path.of("R:", "java-work", "test2.data");
System.out.println(file); // R:\java-work\test2.data

final byte[] bytes = {10, 20, 30, 40, 50, 60};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file,
        StandardOpenOption.READ, StandardOpenOption.WRITE)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());

    buffer.position(2);
    System.out.println(buffer.compact()); // java.nio.DirectByteBuffer[pos=4 lim=6 cap=6]
}

final var ret = Files.readAllBytes(file);
System.out.println(Arrays.toString(ret)); // [30, 40, 50, 60, 50, 60]
final var file = Path.of("R:", "java-work", "test3.data");
System.out.println(file); // R:\java-work\test3.data

final byte[] bytes = {10, 20, 30, 40, 50, 60};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file,
        StandardOpenOption.READ, StandardOpenOption.WRITE)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());

    buffer.position(4);
    System.out.println(buffer.compact()); // java.nio.DirectByteBuffer[pos=2 lim=6 cap=6]
}

final var ret = Files.readAllBytes(file);
System.out.println(Arrays.toString(ret)); // [50, 60, 30, 40, 50, 60]

abstract MappedByteBuffer duplicate ()

このバッファの内容を共有する新しいbyteバッファを作成します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    buffer.position(1);
    buffer.limit(4);

    final var duplicated = buffer.duplicate();

    System.out.println(buffer); // java.nio.DirectByteBufferR[pos=1 lim=4 cap=5]
    System.out.println(duplicated); // java.nio.DirectByteBufferR[pos=1 lim=4 cap=5]

    System.out.println(buffer.get()); // 20
    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40

    System.out.println(duplicated.get()); // 20
    System.out.println(duplicated.get()); // 30
    System.out.println(duplicated.get()); // 40
}

final MappedByteBuffer flip ()

このバッファをフリップ(反転)します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.get()); // 20
    System.out.println(buffer.get()); // 30

    System.out.println(buffer); // java.nio.DirectByteBufferR[pos=3 lim=5 cap=5]
    System.out.println(buffer.flip()); // java.nio.DirectByteBufferR[pos=0 lim=3 cap=5]

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.get()); // 20
    System.out.println(buffer.get()); // 30
}

final MappedByteBuffer force ()

このバッファの内容への変更を、マップされたファイルが格納されている記憶装置へ強制的に書き込みます。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

try (final var channel = FileChannel.open(file, StandardOpenOption.READ,
        StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 3);

    {
        final var bytes = Files.readAllBytes(file);
        System.out.println(Arrays.toString(bytes)); // [0, 0, 0]
    }

    buffer.put((byte) 10);
    buffer.put((byte) 20);
    buffer.put((byte) 30);

    {
        // 注意:自分の環境では、force メソッドの前にファイルへの書き込みが完了している。
        final var bytes = Files.readAllBytes(file);
        System.out.println(Arrays.toString(bytes)); // [10, 20, 30]
    }

    final var ret = buffer.force();
    System.out.println(buffer.equals(ret)); // true

    {
        final var bytes = Files.readAllBytes(file);
        System.out.println(Arrays.toString(bytes)); // [10, 20, 30]
    }
}

final MappedByteBuffer force (int index, int length)

このバッファ・コンテンツのリージョンに対して行われたすべての変更を、マップされたファイルを含むストレージ・デバイスに強制的に書き込みます。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

try (final var channel = FileChannel.open(file, StandardOpenOption.READ,
        StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);

    {
        final var bytes = Files.readAllBytes(file);
        System.out.println(Arrays.toString(bytes)); // [0, 0, 0, 0, 0]
    }

    buffer.put((byte) 10);
    buffer.put((byte) 20);
    buffer.put((byte) 30);

    {
        // 注意:自分の環境では、force メソッドの前にファイルへの書き込みが完了している。
        final var bytes = Files.readAllBytes(file);
        System.out.println(Arrays.toString(bytes)); // [10, 20, 30, 0, 0]
    }

    final var pos = buffer.position();
    System.out.println(pos); // 3

    final var ret = buffer.force(0, pos);
    System.out.println(buffer.equals(ret)); // true

    {
        final var bytes = Files.readAllBytes(file);
        System.out.println(Arrays.toString(bytes)); // [10, 20, 30, 0, 0]
    }
}

final boolean isLoaded ()

このバッファの内容が物理メモリー内にあるかどうかを判断します。

final var os = System.getProperty("os.name");
System.out.println(os); // Windows 10

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    System.out.println(buffer.isLoaded()); // false

    final var ret = buffer.load();
    System.out.println(buffer.equals(ret)); // true

    // Windows では常に false  ...?
    System.out.println(buffer.isLoaded()); // false
}

final MappedByteBuffer limit (int newLimit)

このバッファのリミットを設定します。

final var file = Path.of("R:", "java-work", "test1.data");
System.out.println(file); // R:\java-work\test1.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    System.out.println(buffer); // java.nio.DirectByteBufferR[pos=0 lim=5 cap=5]
    System.out.println(buffer.limit()); // 5

    System.out.println(buffer.limit(3)); // java.nio.DirectByteBufferR[pos=0 lim=3 cap=5]
    System.out.println(buffer.limit()); // 3

    System.out.println(buffer.clear()); // java.nio.DirectByteBufferR[pos=0 lim=5 cap=5]
    System.out.println(buffer.limit()); // 5
}
final var file = Path.of("R:", "java-work", "test2.data");
System.out.println(file); // R:\java-work\test2.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    System.out.println(buffer.limit(3)); // java.nio.DirectByteBufferR[pos=0 lim=3 cap=5]

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.get()); // 20
    System.out.println(buffer.get()); // 30

    try {
        var _ = buffer.get();
    } catch (BufferUnderflowException e) {
        System.out.println("BufferUnderflowException!");
    }

    // 結果
    // ↓
    //BufferUnderflowException!
}

final MappedByteBuffer load ()

このバッファの内容を物理メモリーにロードします。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    {
        // 注意:自分の環境では、load メソッドの前に読み込みが完了している。
        final var dst = new byte[buffer.capacity()];
        buffer.get(0, dst);
        System.out.println(Arrays.toString(dst)); // [10, 20, 30, 40, 50]
    }

    final var ret = buffer.load();
    System.out.println(buffer.equals(ret)); // true

    {
        final var dst = new byte[buffer.capacity()];
        buffer.get(0, dst);
        System.out.println(Arrays.toString(dst)); // [10, 20, 30, 40, 50]
    }
}

final MappedByteBuffer mark ()

このバッファの現在位置にマークを設定します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.get()); // 20

    System.out.println(buffer.position()); // 2
    System.out.println(buffer.mark()); // java.nio.DirectByteBufferR[pos=2 lim=5 cap=5]

    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.get()); // 50

    System.out.println(buffer.position()); // 5
    System.out.println(buffer.reset()); // java.nio.DirectByteBufferR[pos=2 lim=5 cap=5]

    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.get()); // 50
}

final MappedByteBuffer position (int newPosition)

このバッファの位置を設定します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    System.out.println(buffer.position()); // 0

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.position()); // 1

    System.out.println(buffer.get()); // 20
    System.out.println(buffer.position()); // 2

    System.out.println(buffer.get()); // 30
    System.out.println(buffer.position()); // 3

    System.out.println(buffer.get()); // 40
    System.out.println(buffer.position()); // 4

    System.out.println(buffer.get()); // 50
    System.out.println(buffer.position()); // 5

    // java.nio.DirectByteBufferR[pos=3 lim=5 cap=5]
    System.out.println(buffer.position(3));

    System.out.println(buffer.get()); // 40
    System.out.println(buffer.position()); // 4

    System.out.println(buffer.get()); // 50
    System.out.println(buffer.position()); // 5
}

final MappedByteBuffer reset ()

バッファの位置を以前にマークした位置に戻します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.get()); // 20

    System.out.println(buffer.position()); // 2
    System.out.println(buffer.mark()); // java.nio.DirectByteBufferR[pos=2 lim=5 cap=5]

    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.get()); // 50

    System.out.println(buffer.position()); // 5
    System.out.println(buffer.reset()); // java.nio.DirectByteBufferR[pos=2 lim=5 cap=5]

    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.get()); // 50
}

final MappedByteBuffer rewind ()

このバッファをリワインド(巻き戻し)します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    buffer.position(2);
    buffer.limit(4);

    System.out.println(buffer.position()); // 2
    System.out.println(buffer.limit()); // 4

    System.out.println(buffer.rewind()); // java.nio.DirectByteBufferR[pos=0 lim=4 cap=5]

    System.out.println(buffer.position()); // 0
    System.out.println(buffer.limit()); // 4
}

abstract MappedByteBuffer slice ()

このバッファの共有のサブシーケンスを内容とする新しいbyteバッファを作成します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    buffer.position(1);
    buffer.limit(4);

    final var sliced = buffer.slice();

    System.out.println(buffer); // java.nio.DirectByteBufferR[pos=1 lim=4 cap=5]
    System.out.println(sliced); // java.nio.DirectByteBufferR[pos=0 lim=3 cap=3]

    System.out.println(buffer.get()); // 20
    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.hasRemaining()); // false

    System.out.println(sliced.get()); // 20
    System.out.println(sliced.get()); // 30
    System.out.println(sliced.get()); // 40
    System.out.println(sliced.hasRemaining()); // false
}

abstract MappedByteBuffer slice (int index, int length)

このバッファの共有のサブシーケンスを内容とする新しいbyteバッファを作成します。

final var file = Path.of("R:", "java-work", "test.data");
System.out.println(file); // R:\java-work\test.data

final byte[] bytes = {10, 20, 30, 40, 50};
Files.write(file, bytes);

try (final var channel = FileChannel.open(file, StandardOpenOption.READ)) {

    final var buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

    final var sliced = buffer.slice(2, 3);

    System.out.println(buffer); // java.nio.DirectByteBufferR[pos=0 lim=5 cap=5]
    System.out.println(sliced); // java.nio.DirectByteBufferR[pos=0 lim=3 cap=3]

    System.out.println(buffer.get()); // 10
    System.out.println(buffer.get()); // 20
    System.out.println(buffer.get()); // 30
    System.out.println(buffer.get()); // 40
    System.out.println(buffer.get()); // 50
    System.out.println(buffer.hasRemaining()); // false

    System.out.println(sliced.get()); // 30
    System.out.println(sliced.get()); // 40
    System.out.println(sliced.get()); // 50
    System.out.println(sliced.hasRemaining()); // false
}

ByteBufferで宣言されたメソッド

alignedSlice, alignmentOffset, allocate, allocateDirect, array, arrayOffset, asCharBuffer, asDoubleBuffer, asFloatBuffer, asIntBuffer, asLongBuffer, asReadOnlyBuffer, asShortBuffer, compareTo, equals, get, get, get, get, get, get, getChar, getChar, getDouble, getDouble, getFloat, getFloat, getInt, getInt, getLong, getLong, getShort, getShort, hasArray, hashCode, isDirect, mismatch, order, order, put, put, put, put, put, put, put, put, putChar, putChar, putDouble, putDouble, putFloat, putFloat, putInt, putInt, putLong, putLong, putShort, putShort, toString, wrap, wrap

Java API 使用例 : ByteBuffer」をご参照ください。

Bufferで宣言されたメソッド

capacity, hasRemaining, isReadOnly, limit, position, remaining

Java API 使用例 : Buffer」をご参照ください。


関連記事

ページの先頭へ