如何从Java中读取文件夹中的所有文件?

785
如何通过Java读取文件夹中的所有文件?使用哪个API无关紧要。

10
我同意,请指出要使用的类,这样海报就可以熟悉各种方法,否则海报就不会费心去阅读API以查找其他可用的方法。 - camickr
6
你的意思是指一个文件夹中的所有文件,还是包括这个文件夹以及其所有子文件夹中的所有文件? - Jim Garrison
3
API的最新链接:http://docs.oracle.com/javase/7/docs/api/java/io/File.html。 - Tom Duckering
2
如果您使用的是Java 7或更高版本,您可以使用Files.walkFileTree方法,详见https://dev59.com/PXI-5IYBdhLWcg3wc4Cw#23814217。 - micha
35个回答

1137
public void listFilesForFolder(final File folder) {
    for (final File fileEntry : folder.listFiles()) {
        if (fileEntry.isDirectory()) {
            listFilesForFolder(fileEntry);
        } else {
            System.out.println(fileEntry.getName());
        }
    }
}

final File folder = new File("/home/you/Desktop");
listFilesForFolder(folder);

Files.walk API 是从 Java 8 开始可用。

try (Stream<Path> paths = Files.walk(Paths.get("/home/you/Desktop"))) {
    paths
        .filter(Files::isRegularFile)
        .forEach(System.out::println);
} 

这个示例使用了API指南中推荐的try-with-resources模式。它确保无论什么情况下都会关闭流。


13
getName()方法只会返回其所在目录中文件的名称,该目录可能是原始目录的子目录。如果您打算使用此信息来查找文件,则可能会发现getPath()方法返回的路径更有用。 - Tim Parenti
4
我能使用这种方法在整个系统中查找特定类型的文件,比如PDF或HTML吗?我的担忧是效率问题,它是否足够快速,适用于拥有成千上万个文件的系统,还是有更好的替代方案? - Nitin Labhishetty
@codeln 自Java 8以来,性能非常可观,你不会感到任何滞后。它快速、高效,并且足够易读,可以完成你的工作。 - tom_mai78101
22
在Java 8中,您还可以利用filter方法。然后就不再需要使用forEach。请参见此处-> https://dev59.com/PXI-5IYBdhLWcg3wc4Cw#26215931 - Julian Pieles
3
只是为了表明它只被初始化一次。 - rich
显示剩余4条评论

217
File folder = new File("/Users/you/folder/");
File[] listOfFiles = folder.listFiles();

for (File file : listOfFiles) {
    if (file.isFile()) {
        System.out.println(file.getName());
    }
}

2
我认为这将打印目录名称,而不是文件名。 - Fortega
1
比起被接受的答案,这个回答容易理解多了。+1。 - sam1370
2
@sam1370 因为这个程序只读取给定目录下直接包含的文件,而不会读取整个目录中的所有文件。如果给定目录本身包含其他子目录,则它们的内容将不会被读取。 - Farid

171
Java 8中你可以这样做。
Files.walk(Paths.get("/path/to/folder"))
     .filter(Files::isRegularFile)
     .forEach(System.out::println);

以下代码会打印文件夹中的所有文件,但排除所有目录。如果你需要一个列表,可以使用以下代码:

Files.walk(Paths.get("/path/to/folder"))
     .filter(Files::isRegularFile)
     .collect(Collectors.toList())

如果您想返回List<File>而不是List<Path>,只需要进行映射即可:
List<File> filesInFolder = Files.walk(Paths.get("/path/to/folder"))
                                .filter(Files::isRegularFile)
                                .map(Path::toFile)
                                .collect(Collectors.toList());

你还需要确保关闭流!否则,可能会遇到异常,告诉你打开了太多的文件。阅读这里获取更多信息。

3
出现错误:使用.map(Path::toFile)时。此外,应该使用.forEach(path -> System.out.println(path.toString()));而不是.forEach(path -> System.out.println(path.toString); - XaolingBao
2
它说“无效的方法引用,找不到符号”“toFile”方法“toFile”应该是其他东西吗? - XaolingBao
2
请把你的代码粘贴到PasteBin中,好吗?你正在使用java.nio.file.Path吗?我刚刚检查了toFile()方法,即使在Java 8之前也应该存在 -> http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#toFile() - Julian Pieles
2
@NadjibMami 请看这里:http://razem.io/blog/posts/year2015/0819_try_catch_lambda 在评论中回答太复杂了,所以我写了一篇简短的博客文章。 - Julian Pieles
2
如果还有人在寻找 try catch lambda 主题,我的博客链接已经更改 -> https://razem.io/blog/y2015/0819_try_catch_lambda.html。 - Julian Pieles
显示剩余9条评论

36

在这个话题上使用新的Java 8函数的所有答案都忽略了关闭流。 接受答案中的示例应该是:

try (Stream<Path> filePathStream=Files.walk(Paths.get("/home/you/Desktop"))) {
    filePathStream.forEach(filePath -> {
        if (Files.isRegularFile(filePath)) {
            System.out.println(filePath);
        }
    });
}

Files.walk方法的javadoc中:

返回的流封装了一个或多个DirectoryStreams。如果需要及时释放文件系统资源,应使用try-with-resources结构来确保在流操作完成后调用流的close方法。


你不应该使用Stream进行迭代。你获取一个Stream引用,使用它,然后将其丢弃。 - Rudolf Schmidt
@RudolfSchmidt 你的意思是“扔掉它”吗? - Roland
3
我的意思是正确的方法是这样使用的:Files.walk(Paths.get("/home/you/Desktop")).filter(Files::isRegularFile).forEach(filePath->...) - Rudolf Schmidt

35

关于获取目录中所有文件的说明。
方法Files.walk(path)将通过遍历给定启动文件为根的文件树返回所有文件。

例如,下面是一个文件树:

\---folder
    |   file1.txt
    |   file2.txt
    |
    \---subfolder
            file3.txt
            file4.txt

使用 java.nio.file.Files.walk(Path) 方法:

Files.walk(Paths.get("folder"))
        .filter(Files::isRegularFile)
        .forEach(System.out::println);
给出以下结果:
folder\file1.txt
folder\file2.txt
folder\subfolder\file3.txt
folder\subfolder\file4.txt

要获取当前目录中的所有文件,请使用java.nio.file.Files.list(Path)

Files.list(Paths.get("folder"))
        .filter(Files::isRegularFile)
        .forEach(System.out::println);

结果:

folder\file1.txt
folder\file2.txt

2
这应该是2020年现在这个问题的唯一答案了 :) - Arka Mallick
对于 Files.list 的示例点个赞。如果您 不想 递归搜索,这有时可能是最佳选择。 - Per Lundberg
java.nio.file.Files 对我来说出了一些问题,不知道为什么不存在。 - john k
AND,Files.list仅返回文件而不是文件夹。 - FSm
如果我想在所有文件中找到只有 .pdf 的文件怎么办?我该如何使用匹配函数? - Serphentelm

13
import java.io.File;


public class ReadFilesFromFolder {
  public static File folder = new File("C:/Documents and Settings/My Documents/Downloads");
  static String temp = "";

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    System.out.println("Reading files under the folder "+ folder.getAbsolutePath());
    listFilesForFolder(folder);
  }

  public static void listFilesForFolder(final File folder) {

    for (final File fileEntry : folder.listFiles()) {
      if (fileEntry.isDirectory()) {
        // System.out.println("Reading files under the folder "+folder.getAbsolutePath());
        listFilesForFolder(fileEntry);
      } else {
        if (fileEntry.isFile()) {
          temp = fileEntry.getName();
          if ((temp.substring(temp.lastIndexOf('.') + 1, temp.length()).toLowerCase()).equals("txt"))
            System.out.println("File= " + folder.getAbsolutePath()+ "\\" + fileEntry.getName());
        }

      }
    }
  }
}

7
欢迎来到Stack Overflow!请不要仅仅发布一大段代码,还需要解释为什么这段代码可以解决所提出的问题。如果没有解释,那这就不是一个完整的答案。 - Martijn Pieters

13

在Java 7及更高版本中,您可以使用listdir

Path dir = ...;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
    for (Path file: stream) {
        System.out.println(file.getFileName());
    }
} catch (IOException | DirectoryIteratorException x) {
    // IOException can never be thrown by the iteration.
    // In this snippet, it can only be thrown by newDirectoryStream.
    System.err.println(x);
}

你也可以创建一个过滤器,然后将其传递给上面的newDirectoryStream方法

DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
    public boolean accept(Path file) throws IOException {
        try {
            return (Files.isRegularFile(path));
        } catch (IOException x) {
            // Failed to determine if it's a file.
            System.err.println(x);
            return false;
        }
    }
};

查看其他筛选示例,请[参阅文档]。(http://docs.oracle.com/javase/tutorial/essential/io/dirs.html#glob


我对创建过滤器的示例感到困惑。newDirectoryStream.Filter<Path>是什么?你能展示一下它是如何声明的吗? - simgineer
我想我找到问题所在了。这是一个复制粘贴的错误。在“new”和“DirectoryStream.Filter...”之间有一个空格。如果我是正确的,建议您更正您的示例。 - simgineer

11
private static final String ROOT_FILE_PATH="/";
File f=new File(ROOT_FILE_PATH);
File[] allSubFiles=f.listFiles();
for (File file : allSubFiles) {
    if(file.isDirectory())
    {
        System.out.println(file.getAbsolutePath()+" is directory");
        //Steps for directory
    }
    else
    {
        System.out.println(file.getAbsolutePath()+" is file");
        //steps for files
    }
}

这是 Android 从 SD 卡或内部存储读取所有文件和文件夹的解决方案。 - Sanket Thakkar

9

只需使用 Files.walkFileTree(Java 7)遍历所有文件即可。

Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        System.out.println("file: " + file);
        return FileVisitResult.CONTINUE;
    }
});

请注意,如果某个文件或目录的文件属性无法读取(例如由于权限问题),则此代码将抛出异常(而不会报告任何其他文件)。 在 C:\ 上容易重现。 - Thomas S.

5

如果您想要更多选项,可以使用此函数来填充一个包含文件夹中存在的文件的数组列表。选项包括:递归和匹配模式。

public static ArrayList<File> listFilesForFolder(final File folder,
        final boolean recursivity,
        final String patternFileFilter) {

    // Inputs
    boolean filteredFile = false;

    // Ouput
    final ArrayList<File> output = new ArrayList<File> ();

    // Foreach elements
    for (final File fileEntry : folder.listFiles()) {

        // If this element is a directory, do it recursivly
        if (fileEntry.isDirectory()) {
            if (recursivity) {
                output.addAll(listFilesForFolder(fileEntry, recursivity, patternFileFilter));
            }
        }
        else {
            // If there is no pattern, the file is correct
            if (patternFileFilter.length() == 0) {
                filteredFile = true;
            }
            // Otherwise we need to filter by pattern
            else {
                filteredFile = Pattern.matches(patternFileFilter, fileEntry.getName());
            }

            // If the file has a name which match with the pattern, then add it to the list
            if (filteredFile) {
                output.add(fileEntry);
            }
        }
    }

    return output;
}

最好的,埃德里安


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接