1. 概述
在本快速教程中,我们将熟悉几种判断目录是否为空的方法。
2. 使用Files.newDirectoryStream
从Java 7开始,Files.newDirectoryStream方法返回一个DirectoryStream<Path>以迭代目录中的所有条目,因此我们可以使用这个API来检查给定的目录是否为空:
public boolean isEmpty(Path path) throws IOException {
if (Files.isDirectory(path)) {
try (DirectoryStream<Path> directory = Files.newDirectoryStream(path)) {
return !directory.iterator().hasNext();
}
}
return false;
}
对于非目录输入,我们甚至不会尝试加载目录条目,而是返回false:
Path aFile = Paths.get(getClass().getResource("/notDir.txt").toURI());
assertThat(isEmpty(aFile)).isFalse();
另一方面,如果输入是目录,我们将尝试打开指向该目录的DirectoryStream。然后,当且仅当第一个hasNext()方法调用返回false时,我们才会认为该目录为空。否则,它不为空:
Path currentDir = new File("").toPath().toAbsolutePath();
assertThat(isEmpty(currentDir)).isFalse();
DirectoryStream是一个Closeable资源,因此我们将其包装在一个try-with-resources块中。正如我们所料,isEmpty方法对空目录返回true:
Path path = Files.createTempDirectory("tuyucheng-empty");
assertThat(isEmpty(path)).isTrue();
在这里,我们使用Files.createTempDirectory创建一个空的临时目录。
3. 使用Files.list
从JDK 8开始,Files.list方法在内部使用Files.newDirectoryStream API来公开Stream<Path>。每个Path都是给定父目录中的一个条目,因此,我们也可以使用这个API来达到同样的目的:
public boolean isEmpty(Path path) throws IOException {
if (Files.isDirectory(path)) {
try (Stream<Path> entries = Files.list(path)) {
return !entries.findFirst().isPresent();
}
}
return false;
}
同样,我们只使用findFirst方法接触第一个条目。如果返回的Optional为空,则目录也为空。
Stream由I/O资源支持,因此我们确保使用try-with-resources块适当地释放它。
4. 低效的解决方案
Files.list和Files.newDirectoryStream都会惰性地迭代目录条目,因此,它们可以非常高效地处理大型目录。但是,像这样的解决方案在这种情况下效果不佳:
public boolean isEmpty(Path path) {
return path.toFile().listFiles().length == 0;
}
这将急切地加载目录中的所有条目,这在处理大目录时效率非常低。
5. 总结
在这个简短的教程中,我们熟悉了一些检查目录是否为空的有效方法。
Show Disqus Comments
Post Directory
扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章
