JavaSE6以前では、ファイルを再帰的に取得するには、以下のようなコーディングをする必要がありました。
Java
public static void main(String args[]){
File f = new File("C:\\workspace\\sample");
print(f);
}
//再帰的に取得する処理
public static void print(File file){
System.out.println(file.getPath());
File[] fileList = file.listFiles();
if(fileList != null){
for(File f: fileList){
print(f);
}
}
}
実行結果
C:\workspace\sample
C:\workspace\sample\dir2A
C:\workspace\sample\dir2A\dir3
C:\workspace\sample\dir2A\dir3\textA.txt
C:\workspace\sample\dir2A\textA.txt
C:\workspace\sample\dir2A\textB.txt
C:\workspace\sample\dir2B
C:\workspace\sample\dir2B\textA.txt
C:\workspace\sample\dir2B\textB.txt
C:\workspace\sample\textA.txt
JavaSE7以降では、Files#walk
を使用することで、以下のように簡潔にコーディングできるようになりました。
walkメソッドは、深さ優先でファイルツリーを再帰的(トラバース)に辿り、結果をStream
Java
public static void main(String args[]){
try(Stream<Path> stream = Files.walk(Paths.get("C:\\workspace\\sample"))){
stream.forEach(System.out::println);
}catch(IOException e) {
e.printStackTrace();
}
}
実行結果はJavaSE6のときと同じ結果になります。
実行結果
C:\workspace\sample
C:\workspace\sample\dir2A
C:\workspace\sample\dir2A\dir3
C:\workspace\sample\dir2A\dir3\textA.txt
C:\workspace\sample\dir2A\textA.txt
C:\workspace\sample\dir2A\textB.txt
C:\workspace\sample\dir2B
C:\workspace\sample\dir2B\textA.txt
C:\workspace\sample\dir2B\textB.txt
C:\workspace\sample\textA.txt
上記の例ではフォルダも一緒に取得されてしまいます。
通常ファイルのパスのみ取得したい場合は次のように記述します。
Java
//取得したパスが通常ファイルならTrueを返す。
Predicate<? super Path> isRegularFile= p -> {
BasicFileAttributes bfa = null;
try {
bfa = Files.readAttributes(p, BasicFileAttributes.class);
} catch (Exception e) {
e.printStackTrace();
}
return bfa.isRegularFile();
};
//再帰処理して通常ファイルのみパスを出力する。
Files.walk(Paths.get("C:\\workspace\\sample"))
.filter(isRegularFile)
.forEach(System.out::println);
実行結果
C:\workspace\sample\dir2A\dir3\textA.txt
C:\workspace\sample\dir2A\textA.txt
C:\workspace\sample\dir2A\textB.txt
C:\workspace\sample\dir2B\textA.txt
C:\workspace\sample\dir2B\textB.txt
C:\workspace\sample\textA.txt
以下のようにPredicateをもっと簡単に書く方法もあります。
Java
Predicate<? super Path> isRegularFile= p -> {
//通常ファイルならTrue
return Files.isRegularFile(p);
};
Files.walk(Paths.get("C:\\workspace\\sample"))
.filter(isRegularFile)
.forEach(System.out::println);
ディレクトリのパスのみ取得したい場合は次のようにします。
Java
//取得したパスがディレクトリならTrueを返す。
Predicate<? super Path> isDirctory = p -> {
BasicFileAttributes bfa = null;
try {
bfa = Files.readAttributes(p, BasicFileAttributes.class);
} catch (Exception e) {
e.printStackTrace();
}
return bfa.isDirectory();
};
//再帰処理してディレクトリのみパスを出力する。
Files.walk(Paths.get("C:\\workspace\\sample"))
.filter(isDirctory)
.forEach(System.out::println);
実行結果
C:\workspace\sample
C:\workspace\sample\dir2A
C:\workspace\sample\dir2A\dir3
C:\workspace\sample\dir2B
以下のようにPredicateをもっと簡単に書く方法もあります。
Java
Predicate<? super Path> isDirectory= p -> {
//ディレクトリならTrue
return Files.isDirectory(p);
};
Files.walk(Paths.get("C:\\workspace\\sample"))
.filter(isDirectory)
.forEach(System.out::println);
以上で記事の解説はお終い!
もっとJavaやSpringを勉強したい方にはUdemyがオススメ!同僚に差をつけよう!