JavaのwalkFileTreeメソッドの使い方と実践例

java

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

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

        if (dirHierarchy.size() > 1) {
            System.out.print
              ("ディレクトリ「" +
               dirHierarchy.get(dirHierarchy.size() - 2) +
               "」の中身:");
        }
        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(dirHierarchy.size() - 1) +
           "」の中身:");
        System.out.println("ファイル名「" + fileName + "」");

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

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

        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」

いかがでしたでしょうか?

Java7がリリースされてからもう10年近く経ちますが、Javaを昔に勉強した人だとJava7(やJava8)の知識が抜けていることが意外と少なくないと思います。
しかし、Java7では、今回紹介したwalkFileTreeメソッドのように便利なFilesクラスが提供されています。
勉強し直すのは面倒かもしれませんが、新機能を使うことによりコードを簡潔に、かつ安全にすることができるので、勉強する価値はあると思います。

これからも、JavaやC#等で提供されている便利な文法を紹介していきたいと思います!

コメント

タイトルとURLをコピーしました