답변:
File#isDirectory()주어진 파일 (경로)이 디렉토리인지 테스트 하는 데 사용할 수 있습니다 . 이 인 경우 true동일한 메소드를 다시 호출하여 File#listFiles()결과를 얻습니다. 이것을 재귀 라고 합니다.
기본 시작 예는 다음과 같습니다.
public static void main(String... args) {
File[] files = new File("C:/").listFiles();
showFiles(files);
}
public static void showFiles(File[] files) {
for (File file : files) {
if (file.isDirectory()) {
System.out.println("Directory: " + file.getName());
showFiles(file.listFiles()); // Calls same method again.
} else {
System.out.println("File: " + file.getName());
}
}
}
이것은 StackOverflowError트리가 JVM 스택이 보유 할 수있는 것보다 깊을 때에 민감합니다 . 대신 반복적 인 접근 방식이나 꼬리 재귀 를 사용하고 싶을 수도 있지만 다른 주제입니다.)
NullPointerException파일 시스템이 호출 사이에서 변경 될 때 isDirectory와 블록 또는 당신이 정말로 운이 좋지 listFiles않을 때 발생할 수있는 것처럼 변할 수 있습니다 System.out.println. 의 출력이 listFilesnull이 아닌지 확인하면 해당 경쟁 조건이 해결됩니다.
java.nio.file.DirectoryStream을 사용하는 경우 디렉토리를 반복 할 수 있으며 작은 메모리 공간을 갖도록 구현할 수 있지만 확실한 방법은 다음과 같습니다. 특정 플랫폼에서 메모리 사용량을 모니터링합니다.
Java 1.7을 사용중인 경우 다음을 사용할 수 있습니다. java.nio.file.Files.walkFileTree(...) .
예를 들면 다음과 같습니다.
public class WalkFileTreeExample {
public static void main(String[] args) {
Path p = Paths.get("/usr");
FileVisitor<Path> fv = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
};
try {
Files.walkFileTree(p, fv);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Java 8을 사용하는 경우 다음과 함께 스트림 인터페이스를 사용할 수 있습니다 java.nio.file.Files.walk(...).
public class WalkFileTreeExample {
public static void main(String[] args) {
try (Stream<Path> paths = Files.walk(Paths.get("/usr"))) {
paths.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Apache Commons 의 FileUtils 클래스, 특히 iterateFiles를 확인하십시오 .
지정된 디렉토리 (및 선택적으로 서브 디렉토리)의 파일을 반복 할 수 있습니다.
Java 7+의 경우 https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html 도 있습니다.
Javadoc에서 가져온 예제 :
List<Path> listSourceFiles(Path dir) throws IOException {
List<Path> result = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
for (Path entry: stream) {
result.add(entry);
}
} catch (DirectoryIteratorException ex) {
// I/O error encounted during the iteration, the cause is an IOException
throw ex.getCause();
}
return result;
}
@msandiford 응답으로 추가하기 위해, 파일 트리를 걸을 때 대부분의 경우 디렉토리 또는 특정 파일을 방문 할 때 기능을 실행하려고 할 수 있습니다. 스트림을 사용하는 것을 꺼려한다면. 다음 메소드를 재정의 할 수 있습니다.
Files.walkFileTree(Paths.get(Krawl.INDEXPATH), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
// Do someting before directory visit
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
// Do something when a file is visited
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
// Do Something after directory visit
return FileVisitResult.CONTINUE;
}
});
파일 순회에 File.list (FilenameFilter) 및 변형을 잘못 사용할 수도 있습니다. 짧은 코드이며 초기 Java 버전에서 작동합니다. 예 :
// list files in dir
new File(dir).list(new FilenameFilter() {
public boolean accept(File dir, String name) {
String file = dir.getAbsolutePath() + File.separator + name;
System.out.println(file);
return false;
}
});