とあるディレクトリの下にあるファイルを再帰的に探索する必要が最近ありました。Javaの標準apiにそのような機能が用意されていると思いきや、意外もないとのこと。
2016-12-29追記_: 「標準にはない」と書いていますが、実はいろいろあるとのご指摘をいただいています。詳しくはコメント欄を参照してください。
たとえば次のような構造のディレクトリがあるとします。
D:\>tree D:\temp /f
フォルダー パスの一覧: ボリューム Data
ボリューム シリアル番号は C4C7-10BC です
D:\TEMP
│ テキスト0.txt
│
├─フォルダ1
│ │ テキスト1.txt
│ │
│ └─フォルダ1-1
│ テキスト1-1.txt
│
├─フォルダ2
│ テキスト1.txt
│
└─フォルダ3
テキスト3.txt
このD:\temp
の下にあるファイルを再帰的に探索する場合は以下のようにします。
package folder;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class FolderUtils {
public static void main(String[] args) {
String absolutePath = "D:\\temp";
List<File> files = FolderUtils.findAllFile(absolutePath);
for (File file : files) System.out.println(file.getAbsolutePath());
// D:\temp\フォルダ2\テキスト1.txt
// D:\temp\フォルダ1\フォルダ1-1\テキスト1-1.txt
// D:\temp\フォルダ1\テキスト1.txt
// D:\temp\フォルダ3\テキスト3.txt
// D:\temp\テキスト0.txt
}
/**
* 与えられたディレクトリの下にあるファイルを再帰的に探索する。
* @param absolutePath ディレクトリの絶対パス。
* @return ファイルの一覧
*/
public static List<File> findAllFile(String absolutePath) {
List<File> files = new ArrayList<>();
Stack<File> stack = new Stack<>();
stack.add(new File(absolutePath));
while (!stack.isEmpty()) {
File item = stack.pop();
if (item.isFile()) files.add(item);
if (item.isDirectory()) {
for (File child : item.listFiles()) stack.push(child);
}
}
return files;
}
}
アルゴリズムは深さ優先探索。ディレクトリならその直下を探索し、それ以外ならリストに記録するだけの単純なものです。深さ優先探索と相性のいい再帰呼び出しではなく、スタックを用いた実装にしているのは効率的な実装を目指したから――ではなく、単にJavaにスタックがあることを知って使いたかったからです(´・ω・) 大した理由がなくてすみません(´・ω・
)