広告

Java : FileVisitor - API使用例

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


概要

ファイルのビジターです。 このインタフェースの実装は、ファイル・ツリー内の各ファイルをビジットするFiles.walkFileTreeメソッドに渡されます。

クラス構成

FileVisitor インタフェースは、次のようなシーケンスで使われます。

  1. Files.walkFileTree に、基準となるディレクトリと FileVisitor を渡す。
  2. 渡したディレクトリを基準に、その下層のファイルやディレクトリに順々にアクセスする。
  3. アクセス結果は、FileVisitor のコールバックとして受け取る。

単純な実装として、SimpleFileVisitor があります。

// --- PowerShell ---
//PS R:\java-work> tree /F
//...
//R:.
//└─target-dir
//    ├─dir1
//    │      aaa.txt
//    │      bbb.txt
//    │
//    └─dir2
//            ccc.txt
//            ddd.txt

// 対象のディレクトリと、その中のファイル・ディレクトリを削除する例です。
final FileVisitor<Path> visitor = new SimpleFileVisitor<>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        System.out.println("visitFile          : " + file);

        Files.delete(file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
        System.out.println("postVisitDirectory : " + dir);

        if (exc != null) {
            throw exc;
        }

        Files.delete(dir);
        return FileVisitResult.CONTINUE;
    }
};

final var targetDir = Path.of("R:", "java-work", "target-dir");
System.out.println("target dir : " + targetDir);
System.out.println("exists : " + Files.exists(targetDir));

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(targetDir, visitor);

System.out.println("-- walkFileTree : end --");
System.out.println("exists : " + Files.exists(targetDir));

// 結果
// ↓
//target dir : R:\java-work\target-dir
//exists : true
//-- walkFileTree : start --
//visitFile          : R:\java-work\target-dir\dir1\aaa.txt
//visitFile          : R:\java-work\target-dir\dir1\bbb.txt
//postVisitDirectory : R:\java-work\target-dir\dir1
//visitFile          : R:\java-work\target-dir\dir2\ccc.txt
//visitFile          : R:\java-work\target-dir\dir2\ddd.txt
//postVisitDirectory : R:\java-work\target-dir\dir2
//postVisitDirectory : R:\java-work\target-dir
//-- walkFileTree : end --
//exists : false

関連:ディレクトリを丸ごと削除


メソッド

FileVisitResult postVisitDirectory (T dir, IOException exc)

ディレクトリ内のエントリ、およびそのすべての子孫がビジットされたあとにそのディレクトリに対して呼び出されます。

// --- PowerShell ---
//PS R:\java-work> tree /F
//...
//R:.
//│  aaa.txt
//│  bbb.txt
//│
//├─dir1
//│  │  ccc.txt
//│  │  ddd.txt
//│  │
//│  └─dir1-2
//│          eee.txt
//│          fff.txt
//│
//└─dir2
//        ggg.txt
//        hhh.txt

final var start = Path.of("R:", "java-work");
System.out.println("start dir : " + start);

final var visitor = new FileVisitor<Path>() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("preVisitDirectory  : " + dir);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("visitFile          : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.out.println("visitFileFailed    : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.println("postVisitDirectory : " + dir);
        return FileVisitResult.CONTINUE;
    }
};

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(start, visitor);

System.out.println("-- walkFileTree : end --");

// 結果
// ↓
//start dir : R:\java-work
//-- walkFileTree : start --
//preVisitDirectory  : R:\java-work
//visitFile          : R:\java-work\aaa.txt
//visitFile          : R:\java-work\bbb.txt
//preVisitDirectory  : R:\java-work\dir1
//visitFile          : R:\java-work\dir1\ccc.txt
//visitFile          : R:\java-work\dir1\ddd.txt
//preVisitDirectory  : R:\java-work\dir1\dir1-2
//visitFile          : R:\java-work\dir1\dir1-2\eee.txt
//visitFile          : R:\java-work\dir1\dir1-2\fff.txt
//postVisitDirectory : R:\java-work\dir1\dir1-2
//postVisitDirectory : R:\java-work\dir1
//preVisitDirectory  : R:\java-work\dir2
//visitFile          : R:\java-work\dir2\ggg.txt
//visitFile          : R:\java-work\dir2\hhh.txt
//postVisitDirectory : R:\java-work\dir2
//postVisitDirectory : R:\java-work
//-- walkFileTree : end --
final var start = Path.of("R:", "java-work");
System.out.println("start dir : " + start);

final var visitor = new FileVisitor<Path>() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("preVisitDirectory  : " + dir);

        if (Path.of("dir1").equals(dir.getFileName())) {
            System.out.println("                     dir1 SKIP!");
            return FileVisitResult.SKIP_SUBTREE;
        }

        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("visitFile          : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.out.println("visitFileFailed    : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.println("postVisitDirectory : " + dir);
        return FileVisitResult.CONTINUE;
    }
};

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(start, visitor);

System.out.println("-- walkFileTree : end --");

// 結果
// ↓
//start dir : R:\java-work
//-- walkFileTree : start --
//preVisitDirectory  : R:\java-work
//visitFile          : R:\java-work\aaa.txt
//visitFile          : R:\java-work\bbb.txt
//preVisitDirectory  : R:\java-work\dir1
//                     dir1 SKIP!
//preVisitDirectory  : R:\java-work\dir2
//visitFile          : R:\java-work\dir2\ggg.txt
//visitFile          : R:\java-work\dir2\hhh.txt
//postVisitDirectory : R:\java-work\dir2
//postVisitDirectory : R:\java-work
//-- walkFileTree : end --

FileVisitResult preVisitDirectory (T dir, BasicFileAttributes attrs)

ディレクトリ内のエントリがビジットされる前に、そのディレクトリに対して呼び出されます。

// --- PowerShell ---
//PS R:\java-work> tree /F
//...
//R:.
//│  aaa.txt
//│  bbb.txt
//│
//├─dir1
//│  │  ccc.txt
//│  │  ddd.txt
//│  │
//│  └─dir1-2
//│          eee.txt
//│          fff.txt
//│
//└─dir2
//        ggg.txt
//        hhh.txt

final var start = Path.of("R:", "java-work");
System.out.println("start dir : " + start);

final var visitor = new FileVisitor<Path>() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("preVisitDirectory  : " + dir);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("visitFile          : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.out.println("visitFileFailed    : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.println("postVisitDirectory : " + dir);
        return FileVisitResult.CONTINUE;
    }
};

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(start, visitor);

System.out.println("-- walkFileTree : end --");

// 結果
// ↓
//start dir : R:\java-work
//-- walkFileTree : start --
//preVisitDirectory  : R:\java-work
//visitFile          : R:\java-work\aaa.txt
//visitFile          : R:\java-work\bbb.txt
//preVisitDirectory  : R:\java-work\dir1
//visitFile          : R:\java-work\dir1\ccc.txt
//visitFile          : R:\java-work\dir1\ddd.txt
//preVisitDirectory  : R:\java-work\dir1\dir1-2
//visitFile          : R:\java-work\dir1\dir1-2\eee.txt
//visitFile          : R:\java-work\dir1\dir1-2\fff.txt
//postVisitDirectory : R:\java-work\dir1\dir1-2
//postVisitDirectory : R:\java-work\dir1
//preVisitDirectory  : R:\java-work\dir2
//visitFile          : R:\java-work\dir2\ggg.txt
//visitFile          : R:\java-work\dir2\hhh.txt
//postVisitDirectory : R:\java-work\dir2
//postVisitDirectory : R:\java-work
//-- walkFileTree : end --
final var start = Path.of("R:", "java-work");
System.out.println("start dir : " + start);

final var visitor = new FileVisitor<Path>() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("preVisitDirectory  : " + dir);

        if (Path.of("dir1").equals(dir.getFileName())) {
            System.out.println("                     dir1 SKIP!");
            return FileVisitResult.SKIP_SUBTREE;
        }

        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("visitFile          : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.out.println("visitFileFailed    : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.println("postVisitDirectory : " + dir);
        return FileVisitResult.CONTINUE;
    }
};

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(start, visitor);

System.out.println("-- walkFileTree : end --");

// 結果
// ↓
//start dir : R:\java-work
//-- walkFileTree : start --
//preVisitDirectory  : R:\java-work
//visitFile          : R:\java-work\aaa.txt
//visitFile          : R:\java-work\bbb.txt
//preVisitDirectory  : R:\java-work\dir1
//                     dir1 SKIP!
//preVisitDirectory  : R:\java-work\dir2
//visitFile          : R:\java-work\dir2\ggg.txt
//visitFile          : R:\java-work\dir2\hhh.txt
//postVisitDirectory : R:\java-work\dir2
//postVisitDirectory : R:\java-work
//-- walkFileTree : end --

FileVisitResult visitFile (T file, BasicFileAttributes attrs)

ディレクトリ内のファイルに対して呼び出されます。

// --- PowerShell ---
//PS R:\java-work> tree /F
//...
//R:.
//│  aaa.txt
//│  bbb.txt
//│
//├─dir1
//│  │  ccc.txt
//│  │  ddd.txt
//│  │
//│  └─dir1-2
//│          eee.txt
//│          fff.txt
//│
//└─dir2
//        ggg.txt
//        hhh.txt

final var start = Path.of("R:", "java-work");
System.out.println("start dir : " + start);

final var visitor = new FileVisitor<Path>() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("preVisitDirectory  : " + dir);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("visitFile          : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.out.println("visitFileFailed    : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.println("postVisitDirectory : " + dir);
        return FileVisitResult.CONTINUE;
    }
};

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(start, visitor);

System.out.println("-- walkFileTree : end --");

// 結果
// ↓
//start dir : R:\java-work
//-- walkFileTree : start --
//preVisitDirectory  : R:\java-work
//visitFile          : R:\java-work\aaa.txt
//visitFile          : R:\java-work\bbb.txt
//preVisitDirectory  : R:\java-work\dir1
//visitFile          : R:\java-work\dir1\ccc.txt
//visitFile          : R:\java-work\dir1\ddd.txt
//preVisitDirectory  : R:\java-work\dir1\dir1-2
//visitFile          : R:\java-work\dir1\dir1-2\eee.txt
//visitFile          : R:\java-work\dir1\dir1-2\fff.txt
//postVisitDirectory : R:\java-work\dir1\dir1-2
//postVisitDirectory : R:\java-work\dir1
//preVisitDirectory  : R:\java-work\dir2
//visitFile          : R:\java-work\dir2\ggg.txt
//visitFile          : R:\java-work\dir2\hhh.txt
//postVisitDirectory : R:\java-work\dir2
//postVisitDirectory : R:\java-work
//-- walkFileTree : end --
final var start = Path.of("R:", "java-work");
System.out.println("start dir : " + start);

final var visitor = new FileVisitor<Path>() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("preVisitDirectory  : " + dir);

        if (Path.of("dir1").equals(dir.getFileName())) {
            System.out.println("                     dir1 SKIP!");
            return FileVisitResult.SKIP_SUBTREE;
        }

        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("visitFile          : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.out.println("visitFileFailed    : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.println("postVisitDirectory : " + dir);
        return FileVisitResult.CONTINUE;
    }
};

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(start, visitor);

System.out.println("-- walkFileTree : end --");

// 結果
// ↓
//start dir : R:\java-work
//-- walkFileTree : start --
//preVisitDirectory  : R:\java-work
//visitFile          : R:\java-work\aaa.txt
//visitFile          : R:\java-work\bbb.txt
//preVisitDirectory  : R:\java-work\dir1
//                     dir1 SKIP!
//preVisitDirectory  : R:\java-work\dir2
//visitFile          : R:\java-work\dir2\ggg.txt
//visitFile          : R:\java-work\dir2\hhh.txt
//postVisitDirectory : R:\java-work\dir2
//postVisitDirectory : R:\java-work
//-- walkFileTree : end --

FileVisitResult visitFileFailed (T file, IOException exc)

ビジットできなかったファイルに対して呼び出されます。

// --- PowerShell ---
//PS R:\java-work> tree /F
//...
//R:.
//├─dir1
//└─dir2
//        aaa.txt
//
//PS R:\java-work> ls | Get-Acl
//
//    Directory: R:\java-work
//
//Path Owner           Access
//---- -----           ------
//dir1 MY-PC\test-user BUILTIN\Administrators Deny  ReadData…
//dir2 MY-PC\test-user BUILTIN\Administrators Allow  FullControl…

// ※意図的に失敗ケースを発生させるために、dir1ディレクトリは読み取り権限を外しています。

final var start = Path.of("R:", "java-work");
System.out.println("start dir : " + start);

final var visitor = new FileVisitor<Path>() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("preVisitDirectory  : " + dir);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("visitFile          : " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.out.println("visitFileFailed    : " + file);
        System.out.println("IOException        : " + exc);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.println("postVisitDirectory : " + dir);
        return FileVisitResult.CONTINUE;
    }
};

System.out.println("-- walkFileTree : start --");
Files.walkFileTree(start, visitor);

System.out.println("-- walkFileTree : end --");

// 結果
// ↓
//start dir : R:\java-work
//-- walkFileTree : start --
//preVisitDirectory  : R:\java-work
//visitFileFailed    : R:\java-work\dir1
//IOException        : java.nio.file.AccessDeniedException: R:\java-work\dir1
//preVisitDirectory  : R:\java-work\dir2
//visitFile          : R:\java-work\dir2\aaa.txt
//postVisitDirectory : R:\java-work\dir2
//postVisitDirectory : R:\java-work
//-- walkFileTree : end --

関連記事

ページの先頭へ