[java] Java에서 파일을 재귀 적으로 나열

Java에서 디렉토리 아래의 모든 파일을 재귀 적으로 나열하려면 어떻게합니까? 프레임 워크가 유틸리티를 제공합니까?

나는 많은 해키 구현을 보았습니다. 그러나 프레임 워크 나 nio 에서 아무도



답변

Java 8은 트리의 모든 파일을 처리 할 수있는 멋진 스트림을 제공합니다.

Files.walk(Paths.get(path))
        .filter(Files::isRegularFile)
        .forEach(System.out::println);

이것은 파일을 순회하는 자연스러운 방법을 제공합니다. 스트림이므로 제한, 그룹화, 매핑, 조기 종료 등과 같은 결과에 대한 모든 멋진 스트림 작업을 수행 할 수 있습니다.

UPDATE : 나는 또한이 점을 지적 할 수 Files.find 소요 BiPredicate 당신은 파일 특성을 확인해야하는 경우 더 효율적이 될 수 있습니다.

Files.find(Paths.get(path),
           Integer.MAX_VALUE,
           (filePath, fileAttr) -> fileAttr.isRegularFile())
        .forEach(System.out::println);

JavaDoc은이 방법이 Files.walk 보다 더 효율적일 수는 없지만 , 필터 내에서 파일 속성을 검색하는 경우 성능의 차이를 관찰 할 수는 없습니다. 결국 속성을 필터링 해야하는 경우 Files.find를 사용 하고 그렇지 않으면 Files.walk를 사용 하십시오 . 주로 과부하가 있고 더 편리하기 때문입니다.

테스트 : 요청에 따라 많은 답변의 성능 비교를 제공했습니다. 결과 및 테스트 사례가 포함 된 Github 프로젝트를 확인하십시오 .


답변

Fileutils의는iterateFileslistFiles방법. 그들에게 시도하십시오. ( commons-io에서 )

편집 : 당신은 할 수 있습니다 여기 에서 다양한 접근 방식의 벤치 마크를 확인할 . commons-io 접근 방식이 느리므로 여기 에서 더 빠른 것을 선택 하십시오 (중요한 경우)


답변

// 실행할 준비가되었습니다

import java.io.File;

public class Filewalker {

    public void walk( String path ) {

        File root = new File( path );
        File[] list = root.listFiles();

        if (list == null) return;

        for ( File f : list ) {
            if ( f.isDirectory() ) {
                walk( f.getAbsolutePath() );
                System.out.println( "Dir:" + f.getAbsoluteFile() );
            }
            else {
                System.out.println( "File:" + f.getAbsoluteFile() );
            }
        }
    }

    public static void main(String[] args) {
        Filewalker fw = new Filewalker();
        fw.walk("c:\\" );
    }

}


답변

자바 7 것은Files.walkFileTree를 :

시작점과 파일 방문자를 제공하면 파일 트리에서 파일을 탐색 할 때 파일 방문자에 대해 다양한 메소드를 호출합니다. 사람들이 재귀 복사, 재귀 이동, 재귀 삭제 또는 재귀 작업을 개발하는 경우 각 파일에 대해 권한을 설정하거나 다른 작업을 수행하는 경우이를 사용할 것을 기대합니다.

이 질문에 대한 전체 Oracle 튜토리얼이 있습니다.


답변

외부 라이브러리가 필요하지 않습니다.

통화 후 원하는 작업을 수행 할 수 있도록 컬렉션을 반환합니다.

public static Collection<File> listFileTree(File dir) {
    Set<File> fileTree = new HashSet<File>();
    if(dir==null||dir.listFiles()==null){
        return fileTree;
    }
    for (File entry : dir.listFiles()) {
        if (entry.isFile()) fileTree.add(entry);
        else fileTree.addAll(listFileTree(entry));
    }
    return fileTree;
}


답변

나는 다음과 같이 갈 것이다.

public void list(File file) {
    System.out.println(file.getName());
    File[] children = file.listFiles();
    for (File child : children) {
        list(child);
    }
}

System.out.println은 파일과 관련이 있음을 나타냅니다. 일반 파일에는 단순히 자식이 없기 때문에 파일과 디렉토리를 구분할 필요가 없습니다.


답변

이런 종류의 간단한 트래버스에는 재귀보다 큐를 사용하는 것이 좋습니다.

List<File> allFiles = new ArrayList<File>();
Queue<File> dirs = new LinkedList<File>();
dirs.add(new File("/start/dir/"));
while (!dirs.isEmpty()) {
  for (File f : dirs.poll().listFiles()) {
    if (f.isDirectory()) {
      dirs.add(f);
    } else if (f.isFile()) {
      allFiles.add(f);
    }
  }
}