技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

java:walkFileTreeメソッドの使い方

walkFileTreeメソッドとは、ディレクトリ構造を再帰的に走査するメソッドです。
Java7で追加されたFilesクラスが提供するメソッドの一つであり、比較的新しいメソッドです。
(このメソッドの提供により、ディレクトリ構造については自力でCompositeパターンを組む必要がなくなりました)
 
walkFileTreeメソッドの引数は2つあり、1つ目は起点となるパス、2つ目はFileVisitorインターフェースです。
FileVisitorインターフェースにはディレクトリ構造を走査した際の処理が定義されており、FileVisitorインターフェースを利用者が実装することでディレクトリ走査時の具体的な処理内容を記述可能になります。
 
以下、サンプルコードです。
詳しい使い方はWebを調べると出てきますので、必要に応じて調べてみると良いでしょう。
 
【サンプルコード】
・FileVisitorTest.java
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;

// FileVisitorはインタフェースであり、メソッドは定義のみがされている。
// ディレクトリやファイルに訪れた際の処理の中身は自分で実装する。
public class FileVisitorTest implements FileVisitor<Path> {
    private ArrayList<String> dirHierarchy = new ArrayList<>();
    private int currentDepth = -1;

    // 各々のディレクトリの中を走査し始めた時の処理
    @Override
    public FileVisitResult preVisitDirectory
      (Path path, BasicFileAttributes bfa) throws IOException {
        String dirName = path.getFileName().toString();
        currentDepth++;
        if (dirHierarchy.size() == currentDepth) {
            dirHierarchy.add(dirName);
        } else {
            dirHierarchy.set(currentDepth,dirName);
        }

        if (currentDepth > 0) {
            System.out.print
              ("ディレクトリ「" +
               dirHierarchy.get(currentDepth - 1) +
               "」の中身:");
        }
        System.out.println("ディレクトリ名「" + dirName + "」");

        return FileVisitResult.CONTINUE; // 走査継続
    }

    // 走査でファイルを発見した時の処理
    @Override
    public FileVisitResult visitFile
      (Path path, BasicFileAttributes bfa) throws IOException {
        String fileName = path.getFileName().toString();

        System.out.print
          ("ディレクトリ「" +
           dirHierarchy.get(currentDepth) +
           "」の中身:");
        System.out.println("ファイル名「" + fileName + "」");

        return FileVisitResult.CONTINUE; // 走査継続
    }

    // 各々のディレクトリの中を走査し終えた時の処理
    @Override
    public FileVisitResult postVisitDirectory
      (Path path, IOException exc) throws IOException {
        currentDepth--;

        return FileVisitResult.CONTINUE; // 走査継続
    }

    // 走査でファイルの異常を発見した時の処理
    // (ファイルの属性を読み取れない、無限ループ発見、等)
    @Override
    public FileVisitResult visitFileFailed
      (Path path, IOException ex) throws IOException {
        System.out.println(ex.getMessage());

        return FileVisitResult.TERMINATE; // 走査中断
    }

}
 
・WalkFileTreeTestMain.java
import java.io.IOException;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class WalkFileTreeTestMain {
    public static void main(String[ ] args) throws IOException {
        Path startPath = Paths.get("C:\\tmp");
        FileVisitor<Path> fv = new FileVisitorTest();
        // ディレクトリを再帰的に走査するメソッド。
        // 走査時の処理はFileVisitorインターフェースに記述。
        Files.walkFileTree(startPath, fv);
    }
}
 
【テスト用ディレクトリ構造】
C:\tmp>dir /s
 ドライブ C のボリューム ラベルは です
 ボリューム シリアル番号は です

 C:\tmp のディレクト

2020/05/28  22:20    <DIR>          .
2020/05/28  22:20    <DIR>          ..
2020/05/28  22:20    <DIR>          1
2020/05/28  22:20    <DIR>          2
2020/05/28  22:20                 0 3.txt
               1 個のファイル                   0 バイト

 C:\tmp\1 のディレクト

2020/05/28  22:20    <DIR>          .
2020/05/28  22:20    <DIR>          ..
2020/05/28  22:20    <DIR>          11
2020/05/28  22:20    <DIR>          12
2020/05/28  22:20                 0 13.txt
               1 個のファイル                   0 バイト

 C:\tmp\1\11 のディレクト

2020/05/28  22:20    <DIR>          .
2020/05/28  22:20    <DIR>          ..
2020/05/28  22:20                 0 111.txt
2020/05/28  22:20                 0 112.txt
               2 個のファイル                   0 バイト

 C:\tmp\1\12 のディレクト

2020/05/28  22:20    <DIR>          .
2020/05/28  22:20    <DIR>          ..
               0 個のファイル                   0 バイト

 C:\tmp\2 のディレクト

2020/05/28  22:20    <DIR>          .
2020/05/28  22:20    <DIR>          ..
2020/05/28  22:20                 0 21.txt
               1 個のファイル                   0 バイト

     ファイルの総数:
               5 個のファイル       バイト
              14 個のディレクトリ   バイトの空き領域

C:\tmp>
 
【実行結果】
ディレクトリ名「tmp」
ディレクトリ「tmp」の中身:ディレクトリ名「1」
ディレクトリ「1」の中身:ディレクトリ名「11」
ディレクトリ「11」の中身:ファイル名「111.txt」
ディレクトリ「11」の中身:ファイル名「112.txt」
ディレクトリ「1」の中身:ディレクトリ名「12」
ディレクトリ「1」の中身:ファイル名「13.txt」
ディレクトリ「tmp」の中身:ディレクトリ名「2」
ディレクトリ「2」の中身:ファイル名「21.txt」
ディレクトリ「tmp」の中身:ファイル名「3.txt」