広告

Java : FileChannel (ファイル・チャネル) - API使用例

FileChannel (Java SE 20 & JDK 20) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。

注意

  • 基本は Windows 10 で実行した結果となります。
  • 一部 POSIX 環境でないと確認できないものは、Linux で実行しています。

概要

ファイルの読み込み、書き込み、マッピング、操作用チャネルです。

クラス構成

FileChannel クラスは、ファイルに対してバイトデータを読み書きする Channel です。
大きなデータを一度に読み書きするのに向いています。

また、読み書きで使う ByteBuffer はダイレクトバッファに対応しています。
詳細は、下記の API 仕様もご確認ください。

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

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

    final var src = ByteBuffer.allocate(5)
            .put((byte) 10)
            .put((byte) 20)
            .put((byte) 30)
            .put((byte) 40)
            .put((byte) 50)
            .clear();

    final var ret = channel.write(src);
    System.out.println(ret); // 5
}

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

    final var dst = ByteBuffer.allocate(5);
    final var ret = channel.read(dst);
    System.out.println(ret); // 5

    if (dst.hasArray()) {
        // [10, 20, 30, 40, 50]
        System.out.println(Arrays.toString(dst.array()));
    }
}

コンストラクタ

FileChannel ()

このクラスの新しいインスタンスを初期化します。

protectedです。
独自にサブクラスを作ることは少ないと思いますので、コード例は割愛します。

メソッド

abstract void force (boolean metaData)

このチャネルのファイルの更新内容は、その記憶装置に強制的に書き込まれます。

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

System.out.println(Files.notExists(path)); // true

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

    final byte[] array = {10, 20, 30, 40, 50};
    final var src = ByteBuffer.wrap(array);

    // --- PowerShell ---
    //PS R:\java-work> ls | Format-Table -Property Length, Name
    //
    //Length Name
    //------ ----
    //     0 test.data

    System.out.println(channel.write(src)); // 5
    System.out.println(channel.size()); // 5

    // --- PowerShell ---
    //PS R:\java-work> ls | Format-Table -Property Length, Name
    //
    //Length Name
    //------ ----
    //     0 test.data

    // ※ 実際のファイルサイズは、まだ 0 です。

    channel.force(true);

    // --- PowerShell ---
    //PS R:\java-work> ls | Format-Table -Property Length, Name
    //
    //Length Name
    //------ ----
    //     5 test.data
}

final FileLock lock ()

このチャネルのファイル上に排他ロックを設定します。

関連 : FileLock

public class Child {
    public static void main(String[] args) throws IOException, InterruptedException {
        if (args.length != 1) {
            throw new IllegalArgumentException();
        }

        final var name = "child " + args[0];

        final var file = Path.of("lock.txt");
        try (final var channel = FileChannel.open(
                file, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {

            System.out.printf("  %s : lock start ...%n", name);
            try (final var lock = channel.lock()) {

                TimeUnit.MILLISECONDS.sleep(100);

                System.out.printf("  %s :   *** lock OK! ***%n", name);
                System.out.printf("  %s :   sleep 5 seconds ...%n", name);

                TimeUnit.SECONDS.sleep(5);
                System.out.printf("  %s :   sleep end%n", name);
            }

            System.out.printf("  %s : lock end%n", name);
        }
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var p1 = new ProcessBuilder("java", "Child", "1").inheritIO().start();
        TimeUnit.MILLISECONDS.sleep(10);
        final var p2 = new ProcessBuilder("java", "Child", "2").inheritIO().start();

        p1.waitFor();
        p2.waitFor();

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//  child 1 : lock start ...
//  child 2 : lock start ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 5 seconds ...
//  child 1 :   sleep end
//  child 1 : lock end
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 5 seconds ...
//  child 2 :   sleep end
//  child 2 : lock end
//main : end

abstract FileLock lock (long position, long size, boolean shared)

このチャネルのファイルの指定された領域をロックします。

positionsize パラメータの例。

public class Child {
    public static void main(String[] args) throws IOException, InterruptedException {
        if (args.length != 3) {
            throw new IllegalArgumentException();
        }

        final var name = "child " + args[0];
        final var position = Long.parseLong(args[1]);
        final var size = Long.parseLong(args[2]);

        final var file = Path.of("lock.txt");
        try (final var channel = FileChannel.open(
                file, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {

            System.out.printf("  %s : lock start (position=%d, size=%d) ...%n",
                    name, position, size);
            try (final var lock = channel.lock(position, size, false)) {

                TimeUnit.MILLISECONDS.sleep(100);

                System.out.printf("  %s :   *** lock OK! ***%n", name);
                System.out.printf("  %s :   sleep 5 seconds ...%n", name);

                TimeUnit.SECONDS.sleep(5);
                System.out.printf("  %s :   sleep end%n", name);
            }

            System.out.printf("  %s : lock end%n", name);
        }
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        if (args.length != 2) {
            throw new IllegalArgumentException();
        }

        System.out.println("main : start");

        final var p1 = new ProcessBuilder("java", "Child", "1", "0", "10").inheritIO().start();
        TimeUnit.MILLISECONDS.sleep(10);
        final var p2 = new ProcessBuilder("java", "Child", "2", args[0], args[1]).inheritIO().start();

        p1.waitFor();
        p2.waitFor();

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main 0 10
//main : start
//  child 1 : lock start (position=0, size=10) ...
//  child 2 : lock start (position=0, size=10) ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 5 seconds ...
//  child 1 :   sleep end
//  child 1 : lock end
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 5 seconds ...
//  child 2 :   sleep end
//  child 2 : lock end
//main : end
//
//> java Main 11 5
//main : start
//  child 1 : lock start (position=0, size=10) ...
//  child 2 : lock start (position=11, size=5) ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 5 seconds ...
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 5 seconds ...
//  child 1 :   sleep end
//  child 1 : lock end
//  child 2 :   sleep end
//  child 2 : lock end
//main : end

shared パラメータの例。

public class Child {
    public static void main(String[] args) throws IOException, InterruptedException {
        if (args.length != 2) {
            throw new IllegalArgumentException();
        }

        final var name = "child " + args[0];
        final var shared = "shared".equals(args[1]);

        final var file = Path.of("lock.txt");
        try (final var channel = FileChannel.open(file, StandardOpenOption.CREATE,
                StandardOpenOption.WRITE, StandardOpenOption.READ)) {

            System.out.printf("  %s : lock start (shared=%b) ...%n", name, shared);
            try (final var lock = channel.lock(0, Long.MAX_VALUE, shared)) {

                TimeUnit.MILLISECONDS.sleep(100);

                System.out.printf("  %s :   *** lock OK! ***%n", name);
                System.out.printf("  %s :   sleep 5 seconds ...%n", name);

                TimeUnit.SECONDS.sleep(5);
                System.out.printf("  %s :   sleep end%n", name);
            }

            System.out.printf("  %s : lock end%n", name);
        }
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        if (args.length != 2) {
            throw new IllegalArgumentException();
        }

        System.out.println("main : start");

        final var p1 = new ProcessBuilder("java", "Child", "1", args[0]).inheritIO().start();
        TimeUnit.MILLISECONDS.sleep(10);
        final var p2 = new ProcessBuilder("java", "Child", "2", args[1]).inheritIO().start();

        p1.waitFor();
        p2.waitFor();

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main shared shared
//main : start
//  child 1 : lock start (shared=true) ...
//  child 2 : lock start (shared=true) ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 5 seconds ...
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 5 seconds ...
//  child 1 :   sleep end
//  child 1 : lock end
//  child 2 :   sleep end
//  child 2 : lock end
//main : end
//
//> java Main shared exclusive
//main : start
//  child 1 : lock start (shared=true) ...
//  child 2 : lock start (shared=false) ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 5 seconds ...
//  child 1 :   sleep end
//  child 1 : lock end
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 5 seconds ...
//  child 2 :   sleep end
//  child 2 : lock end
//main : end
//
//> java Main exclusive shared
//main : start
//  child 1 : lock start (shared=false) ...
//  child 2 : lock start (shared=true) ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 5 seconds ...
//  child 1 :   sleep end
//  child 1 : lock end
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 5 seconds ...
//  child 2 :   sleep end
//  child 2 : lock end
//main : end
//
//> java Main exclusive exclusive
//main : start
//  child 1 : lock start (shared=false) ...
//  child 2 : lock start (shared=false) ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 5 seconds ...
//  child 1 :   sleep end
//  child 1 : lock end
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 5 seconds ...
//  child 2 :   sleep end
//  child 2 : lock end
//main : end

abstract MappedByteBuffer map (FileChannel.MapMode mode, long position, long size)

このチャネルのファイルの領域を直接メモリーにマッピングします。

関連 : MappedByteBuffer

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

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

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

    final var buffer = channel.map(
            FileChannel.MapMode.READ_WRITE, 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(path);
        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(path);
        System.out.println(Arrays.toString(ret)); // [-10, -20, -30, 40, 50]
    }
}

MemorySegmentPREVIEW map (FileChannel.MapMode mode, long offset, long size, SegmentScopePREVIEW session)

Preview. 指定されたオフセット、サイズ、およびメモリー・セッションを使用して、このチャネル・ファイルのリージョンを新しいマップ済みメモリー・セグメントにマップします。

プレビュー機能のためコード例は割愛します。

static FileChannel open (Path path, OpenOption... options)

ファイルを開くか作成し、そのファイルにアクセスするためのファイル・チャネルを返します。

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

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

    final var src = ByteBuffer.allocate(5)
            .put((byte) 10)
            .put((byte) 20)
            .put((byte) 30)
            .put((byte) 40)
            .put((byte) 50)
            .clear();

    final var ret = channel.write(src);
    System.out.println(ret); // 5
}

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

    final var dst = ByteBuffer.allocate(5);
    final var ret = channel.read(dst);
    System.out.println(ret); // 5

    if (dst.hasArray()) {
        // [10, 20, 30, 40, 50]
        System.out.println(Arrays.toString(dst.array()));
    }
}

static FileChannel open (Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs)

ファイルを開くか作成し、そのファイルにアクセスするためのファイル・チャネルを返します。

attrs パラメータ以外については、open(Path path, OpenOption... options) の使用例をご参照ください。

※ FileAttribute を使うために、以下のコード例は Linux 上で実行しています。

public class Main {
    public static void main(String[] args) throws IOException {
        System.out.println(System.getProperty("os.name")); // Linux

        {
            final var file = Path.of("sample1.txt");
            try (final var channel = FileChannel.open(file,
                    Set.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE))) {
            }

            // --- Linux Terminal ---
            //$ ls -l sample1.txt
            //-rw-rw-r-- 1 xxxx xxxx 0 Sep 27 17:18 sample1.txt
        }

        {
            final var permissions = PosixFilePermissions.fromString("rw-r-----");
            final var attrs = PosixFilePermissions.asFileAttribute(permissions);

            final var file = Path.of("sample2.txt");
            try (final var channel = FileChannel.open(file,
                    Set.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE),
                    attrs)) {
            }

            // --- Linux Terminal ---
            //$ ls -l sample2.txt
            //-rw-r----- 1 xxxx xxxx 0 Sep 27 17:18 sample2.txt
        }
    }
}

abstract long position ()

このチャネルのファイル位置を返します。

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

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

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

    final var ret1 = channel.position(2);
    System.out.println(channel.equals(ret1)); // true

    {
        System.out.println(channel.position()); // 2

        final var buffer = ByteBuffer.allocate(3);
        final var ret = channel.read(buffer);
        System.out.println(ret); // 3

        System.out.println(channel.position()); // 5

        if (buffer.hasArray()) {
            // [30, 40, 50]
            System.out.println(Arrays.toString(buffer.array()));
        }
    }

    final var ret2 = channel.position(0);
    System.out.println(channel.equals(ret2)); // true

    {
        System.out.println(channel.position()); // 0

        final var buffer = ByteBuffer.allocate(5);
        final var ret = channel.read(buffer);
        System.out.println(ret); // 5

        System.out.println(channel.position()); // 5

        if (buffer.hasArray()) {
            // [10, 20, 30, 40, 50]
            System.out.println(Arrays.toString(buffer.array()));
        }
    }
}

abstract FileChannel position (long newPosition)

このチャネルのファイル位置を設定します。

このメソッドの使用例は、position() にまとめて記載しました。
そちらのAPI使用例をご参照ください。

abstract int read (ByteBuffer dst)

このチャネルのバイト・シーケンスを指定のバッファに読み込みます。

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

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

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

    final var array = new byte[5];
    final var dst = ByteBuffer.wrap(array);

    System.out.println(dst); // java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
    System.out.println(Arrays.toString(array)); // [0, 0, 0, 0, 0]

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

    final var ret = channel.read(dst);
    System.out.println(ret); // 3

    System.out.println(channel.position()); // 3

    System.out.println(dst); // java.nio.HeapByteBuffer[pos=3 lim=5 cap=5]
    System.out.println(Arrays.toString(array)); // [10, 20, 30, 0, 0]
}

final long read (ByteBuffer[] dsts)

このチャネルのバイト・シーケンスを指定されたバッファに読み込みます。

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

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

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

    final ByteBuffer[] dsts = {
            ByteBuffer.allocate(2),
            ByteBuffer.allocate(3),
            ByteBuffer.allocate(4),
    };

    final var ret = channel.read(dsts);
    System.out.println(ret); // 9

    System.out.println("-- dsts --");
    for (final var dst : dsts) {
        if (dst.hasArray()) {
            System.out.println(Arrays.toString(dst.array()));
        }
    }

    // 結果
    // ↓
    //-- dsts --
    //[10, 20]
    //[30, 40, 50]
    //[60, 70, 80, 90]
}

abstract long read (ByteBuffer[] dsts, int offset, int length)

このチャネルのバイト・シーケンスを指定されたバッファのサブシーケンスに読み込みます。

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

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

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

    final ByteBuffer[] dsts = {
            ByteBuffer.allocate(1),
            ByteBuffer.allocate(2),
            ByteBuffer.allocate(3),
            ByteBuffer.allocate(4),
            ByteBuffer.allocate(5),
    };

    final var ret = channel.read(dsts, 1, 3);
    System.out.println(ret); // 9

    System.out.println("-- dsts --");
    for (final var dst : dsts) {
        if (dst.hasArray()) {
            System.out.println(Arrays.toString(dst.array()));
        }
    }

    // 結果
    // ↓
    //-- dsts --
    //[0]
    //[10, 20]
    //[30, 40, 50]
    //[60, 70, 80, 90]
    //[0, 0, 0, 0, 0]
}

abstract int read (ByteBuffer dst, long position)

このチャネルのバイト・シーケンスを、指定されたファイル位置からバッファに読み込みます。

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

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

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

    final var array = new byte[5];
    final var dst = ByteBuffer.wrap(array);

    System.out.println(dst); // java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
    System.out.println(Arrays.toString(array)); // [0, 0, 0, 0, 0]

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

    final var ret = channel.read(dst, 2);
    System.out.println(ret); // 3

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

    System.out.println(dst); // java.nio.HeapByteBuffer[pos=3 lim=5 cap=5]
    System.out.println(Arrays.toString(array)); // [30, 40, 50, 0, 0]
}

abstract long size ()

このチャネルのファイルの現在のサイズを返します。

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

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

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

    final var size = channel.size();
    System.out.println(size); // 5

    final var dst = ByteBuffer.allocate(Math.toIntExact(size));
    System.out.println(channel.read(dst)); // 5

    if (dst.hasArray()) {
        // [10, 20, 30, 40, 50]
        System.out.println(Arrays.toString(dst.array()));
    }
}

abstract long transferFrom (ReadableByteChannel src, long position, long count)

指定された読込み可能なバイト・チャネルからこのチャネルのファイルへバイトを転送します。

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

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

Files.write(srcPath, new byte[]{10, 20, 30});

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

    System.out.println(channel.size()); // 0

    try (final var src = FileChannel.open(srcPath, StandardOpenOption.READ)) {

        final var ret = channel.transferFrom(src, 0, src.size());
        System.out.println(ret); // 3
    }
}

final var bytes = Files.readAllBytes(dstPath);
System.out.println(Arrays.toString(bytes)); // [10, 20, 30]
final var srcPath = Path.of("R:", "java-work", "src.data");
System.out.println(srcPath); // R:\java-work\src.data

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

Files.write(srcPath, new byte[]{10, 20, 30});
Files.write(dstPath, new byte[]{-1, -2, -3, -4, -5, -6, -7});

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

    System.out.println(channel.size()); // 7

    try (final var src = FileChannel.open(srcPath, StandardOpenOption.READ)) {

        final var ret = channel.transferFrom(src, 2, 3);
        System.out.println(ret); // 3
    }
}

final var bytes = Files.readAllBytes(dstPath);
System.out.println(Arrays.toString(bytes)); // [-1, -2, 10, 20, 30, -6, -7]

abstract long transferTo (long position, long count, WritableByteChannel target)

このチャネルのファイルから指定された書込み可能なバイト・チャネルへバイトを転送します。

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

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

Files.write(srcPath, new byte[]{10, 20, 30});

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

    System.out.println(channel.size()); // 3

    try (final var target = FileChannel.open(dstPath,
            StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {

        final var ret = channel.transferTo(0, channel.size(), target);
        System.out.println(ret); // 3
    }
}

final var bytes = Files.readAllBytes(dstPath);
System.out.println(Arrays.toString(bytes)); // [10, 20, 30]
final var srcFile = Path.of("R:", "java-work", "src.data");
System.out.println(srcFile); // R:\java-work\src.data

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

Files.write(srcFile, new byte[]{10, 20, 30, 40, 50, 60, 70});

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

    System.out.println(channel.size()); // 7

    try (final var target = FileChannel.open(dstFile,
            StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {

        final var ret = channel.transferTo(2, 3, target);
        System.out.println(ret); // 3
    }
}

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

abstract FileChannel truncate (long size)

このチャネルのファイルの末尾を切詰め、指定されたサイズにします。

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

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

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

    final var ret = channel.truncate(3);
    System.out.println(channel.equals(ret)); // true

    final var size = channel.size();
    System.out.println(size); // 3
}

// [10, 20, 30]
System.out.println(Arrays.toString(Files.readAllBytes(path)));

final FileLock tryLock ()

このチャネルのファイル上で排他ロックを獲得しようとします。

関連 : FileLock

public class Child {
    public static void main(String[] args) throws IOException, InterruptedException {
        if (args.length != 1) {
            throw new IllegalArgumentException();
        }

        final var name = "child " + args[0];

        final var file = Path.of("lock.txt");
        try (final var channel = FileChannel.open(
                file, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {

            System.out.printf("  %s : lock start ...%n", name);

            // ロックが取れるまで繰り返します。
            while (true) {
                try (final var lock = channel.tryLock()) {

                    TimeUnit.MILLISECONDS.sleep(100);

                    if (lock != null) {
                        System.out.printf("  %s :   *** lock OK! ***%n", name);
                        System.out.printf("  %s :   sleep 3 seconds ...%n", name);
                        TimeUnit.SECONDS.sleep(3);
                        break;
                    } else {
                        System.out.printf("  %s :   ### lock NG! ###%n", name);
                        System.out.printf("  %s :   sleep 1 second ...%n", name);
                        TimeUnit.SECONDS.sleep(1);
                    }
                }
            }

            System.out.printf("  %s : lock end%n", name);
        }
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var p1 = new ProcessBuilder("java", "Child", "1").inheritIO().start();
        TimeUnit.MILLISECONDS.sleep(10);
        final var p2 = new ProcessBuilder("java", "Child", "2").inheritIO().start();

        p1.waitFor();
        p2.waitFor();

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//  child 1 : lock start ...
//  child 2 : lock start ...
//  child 1 :   *** lock OK! ***
//  child 1 :   sleep 3 seconds ...
//  child 2 :   ### lock NG! ###
//  child 2 :   sleep 1 second ...
//  child 2 :   ### lock NG! ###
//  child 2 :   sleep 1 second ...
//  child 2 :   ### lock NG! ###
//  child 2 :   sleep 1 second ...
//  child 1 : lock end
//  child 2 :   *** lock OK! ***
//  child 2 :   sleep 3 seconds ...
//  child 2 : lock end
//main : end

abstract FileLock tryLock (long position, long size, boolean shared)

このチャネルのファイルの指定された領域でロックを獲得しようとします。

本メソッドの基本的な動作は tryLock() の使用例をご参照ください。
また、各パラメータについては、lock(long position, long size, boolean shared) の使用例をご参照ください。

abstract int write (ByteBuffer src)

このチャネルのバイト・シーケンスを指定のバッファから書き出します。

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

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

    final byte[] array = {10, 20, 30, 40, 50};
    final var src = ByteBuffer.wrap(array);

    System.out.println(src); // java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
    System.out.println(channel.position()); // 0

    final var ret = channel.write(src);
    System.out.println(ret); // 5

    System.out.println(src); // java.nio.HeapByteBuffer[pos=5 lim=5 cap=5]
    System.out.println(channel.position()); // 5
}

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

final long write (ByteBuffer[] srcs)

このチャネルのバイト・シーケンスを指定されたバッファから書き出します。

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

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

    final ByteBuffer[] srcs = {
            ByteBuffer.wrap(new byte[]{10, 20}),
            ByteBuffer.wrap(new byte[]{30, 40, 50}),
            ByteBuffer.wrap(new byte[]{60, 70, 80, 90}),
    };

    final var ret = channel.write(srcs);
    System.out.println(ret); // 9
}

final var bytes = Files.readAllBytes(path);

// [10, 20, 30, 40, 50, 60, 70, 80, 90]
System.out.println(Arrays.toString(bytes));

abstract long write (ByteBuffer[] srcs, int offset, int length)

このチャネルのバイト・シーケンスを指定されたバッファのサブシーケンスから書き出します。

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

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

    final ByteBuffer[] srcs = {
            ByteBuffer.wrap(new byte[]{10}),
            ByteBuffer.wrap(new byte[]{20, 30}),
            ByteBuffer.wrap(new byte[]{40, 50, 60}),
            ByteBuffer.wrap(new byte[]{70, 80, 90, 100}),
    };

    final var ret = channel.write(srcs, 1, 2);
    System.out.println(ret); // 5
}

final var bytes = Files.readAllBytes(path);

// [20, 30, 40, 50, 60]
System.out.println(Arrays.toString(bytes));

abstract int write (ByteBuffer src, long position)

指定されたバッファのバイト・シーケンスをこのチャネルの指定されたファイル位置に書き込みます。

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

Files.write(path, new byte[]{-1, -2, -3, -4, -5, -6, -7});

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

    final byte[] array = {10, 20, 30};
    final var src = ByteBuffer.wrap(array);

    System.out.println(src); // java.nio.HeapByteBuffer[pos=0 lim=3 cap=3]
    System.out.println(channel.position()); // 0

    final var ret = channel.write(src, 2);
    System.out.println(ret); // 3

    System.out.println(src); // java.nio.HeapByteBuffer[pos=3 lim=3 cap=3]
    System.out.println(channel.position()); // 0
}

final var bytes = Files.readAllBytes(path);
System.out.println(Arrays.toString(bytes)); // [-1, -2, 10, 20, 30, -6, -7]

AbstractInterruptibleChannelで宣言されたメソッド

begin, close, end, implCloseChannel, isOpen

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

Channelで宣言されたメソッド

isOpen

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


関連記事

ページの先頭へ