Answers:
您可以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块或者你只是得到真正倒霉。检查的输出listFiles不为null将解决该竞争条件。
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,则可以将stream接口用于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的百科全书类-特别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;
}
});