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

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


当前回答

Kotlin为此使用了FileTreeWalk。例如:

dataDir.walkTopDown().filter { !it.isDirectory }.joinToString("\n") {
   "${it.toRelativeString(dataDir)}: ${it.length()}"
}

将生成给定根下所有非目录文件的文本列表,每行一个文件,其路径相对于根和长度。

其他回答

具有单个列表的非递归BFS(特定的示例是搜索*。eml文件):

    final FileFilter filter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            return file.isDirectory() || file.getName().endsWith(".eml");
        }
    };

    // BFS recursive search
    List<File> queue = new LinkedList<File>();
    queue.addAll(Arrays.asList(dir.listFiles(filter)));

    for (ListIterator<File> itr = queue.listIterator(); itr.hasNext();) {
        File file = itr.next();
        if (file.isDirectory()) {
            itr.remove();
            for (File f: file.listFiles(filter)) itr.add(f);
        }
    }

除了递归遍历,还可以使用基于访问者的方法。

下面的代码是使用基于访问者的遍历方法。我们期望程序的输入是要遍历的根目录。

public interface Visitor {
    void visit(DirElement d);
    void visit(FileElement f);
}

public abstract class Element {
    protected File rootPath;
    abstract void accept(Visitor v);

    @Override
    public String toString() {
        return rootPath.getAbsolutePath();
    }
}

public class FileElement extends Element {
    FileElement(final String path) {
        rootPath = new File(path);
    }

    @Override
    void accept(final Visitor v) {
        v.visit(this);
    }
}

public class DirElement extends Element implements Iterable<Element> {
    private final List<Element> elemList;
    DirElement(final String path) {
        elemList = new ArrayList<Element>();
        rootPath = new File(path);
        for (File f : rootPath.listFiles()) {
            if (f.isDirectory()) {
                elemList.add(new DirElement(f.getAbsolutePath()));
            } else if (f.isFile()) {
                elemList.add(new FileElement(f.getAbsolutePath()));
            }
        }
    }

    @Override
    void accept(final Visitor v) {
        v.visit(this);
    }

    public Iterator<Element> iterator() {
        return elemList.iterator();
    }
}

public class ElementWalker {
    private final String rootDir;
    ElementWalker(final String dir) {
        rootDir = dir;
    }

    private void traverse() {
        Element d = new DirElement(rootDir);
        d.accept(new Walker());
    }

    public static void main(final String[] args) {
        ElementWalker t = new ElementWalker("C:\\temp");
        t.traverse();
    }

    private class Walker implements Visitor {
        public void visit(final DirElement d) {
            System.out.println(d);
            for(Element e:d) {
                e.accept(this);
            }
        }

        public void visit(final FileElement f) {
            System.out.println(f);
        }
    }
}

不需要外部库。 返回一个集合,这样你就可以在调用后对它做任何你想做的事情。

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;
}

示例输出*.csv文件在目录递归搜索子目录使用files .find()从java.nio:

String path = "C:/Daten/ibiss/ferret/";
    logger.debug("Path:" + path);
    try (Stream<Path> fileList = Files.find(Paths.get(path), Integer.MAX_VALUE,
            (filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toString().endsWith("csv"))) {
        List<String> someThingNew = fileList.sorted().map(String::valueOf).collect(Collectors.toList());
        for (String t : someThingNew) {
            t.toString();
            logger.debug("Filename:" + t);
        }

    }

发布这个例子,因为我有困难理解如何在布莱恩给出的#1个例子中传递文件名参数,使用foreach对流结果-

希望这能有所帮助。

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

文件。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);
}