我如何递归地列出在Java目录下的所有文件?框架是否提供任何实用程序?

我看到了很多俗气的实现。但没有来自框架或nio


当前回答

在Java 7中,你可以使用以下类:

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

public class MyFileIterator extends SimpleFileVisitor<Path>
{
    public MyFileIterator(String path) throws Exception
    {
        Files.walkFileTree(Paths.get(path), this);
    }

    @Override
    public FileVisitResult visitFile(Path file,
            BasicFileAttributes attributes) throws IOException
    {
        System.out.println("File: " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir,
            BasicFileAttributes attributes) throws IOException
    {
        System.out.println("Dir: " + dir);
        return FileVisitResult.CONTINUE;
    }
}

其他回答

我的建议是:

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

System.out.println只是用来指示对该文件执行一些操作。没有必要区分文件和目录,因为一个正常的文件只会有零个子文件。

我的版本(当然我可以在Java 8中使用内置的walk;-)):

public static List<File> findFilesIn(File rootDir, Predicate<File> predicate) {
        ArrayList<File> collected = new ArrayList<>();
        walk(rootDir, predicate, collected);
        return collected;
    }

    private static void walk(File dir, Predicate<File> filterFunction, List<File> collected) {
        Stream.of(listOnlyWhenDirectory(dir))
                .forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction)));
    }

    private static File[] listOnlyWhenDirectory(File dir) {
        return dir.isDirectory() ? dir.listFiles() : new File[]{};
    }

    private static List<File> addAndReturn(List<File> files, File toAdd, Predicate<File> filterFunction) {
        if (filterFunction.test(toAdd)) {
            files.add(toAdd);
        }
        return files;
    }

列出所有文件提供的扩展名,与选项扫描 子文件夹(递归)

 public static ArrayList<File> listFileTree(File dir,boolean recursive) {
        if (null == dir || !dir.isDirectory()) {
            return new ArrayList<>();
        }
        final Set<File> fileTree = new HashSet<File>();
        FileFilter fileFilter = new FileFilter() {
            private final String[] acceptedExtensions = new String[]{"jpg", "png", "webp", "jpeg"};

            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }
                for (String extension : acceptedExtensions) {
                    if (file.getName().toLowerCase().endsWith(extension)) {
                        return true;
                    }
                }
                return false;
            }
        };
        File[] listed = dir.listFiles(fileFilter);
        if(listed!=null){
            for (File entry : listed) {
                if (entry.isFile()) {
                    fileTree.add(entry);
                } else if(recursive){
                    fileTree.addAll(listFileTree(entry,true));
                }
            }
        }
        return new ArrayList<>(fileTree);
    }

即使有人已经提供了Java 8 walk,您也可以这样做。

它将递归地为您提供所有文件

  private Stream<File> files(File file) {
    return file.isDirectory()
            ? Arrays.stream(file.listFiles()).flatMap(this::files)
            : Stream.of(file);
}

接受的答案很差,因为它可能导致资源泄漏。

文件。walk由DirectoryStreams支持。

返回的流封装了一个或多个directorystream。如果需要及时处理文件系统资源,则应该使用try-with-resources构造来确保在流操作完成后调用流的close方法。对关闭的流进行操作将导致IllegalStateException异常。

DirectoryStream必须在它的javadoc中指定关闭:

DirectoryStream在创建时打开,并通过调用close方法关闭。关闭目录流将释放与该流关联的所有资源。关闭流失败可能导致资源泄漏。try-with-resources语句提供了一个有用的结构来确保流是关闭的:

Path dir = ...
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
    for (Path entry: stream) {
        ...
    }
}

因此,正确的答案是:

try (Stream<Path> stream = Files.walk(Paths.get(path))) {
    // Do something with the stream.
    stream.filter(Files::isRegularFile)
          .forEach(System.out::println);
}