我如何递归地列出在Java目录下的所有文件?框架是否提供任何实用程序?
我看到了很多俗气的实现。但没有来自框架或nio
我如何递归地列出在Java目录下的所有文件?框架是否提供任何实用程序?
我看到了很多俗气的实现。但没有来自框架或nio
当前回答
不需要外部库。 返回一个集合,这样你就可以在调用后对它做任何你想做的事情。
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;
}
其他回答
这里有一个使用递归的简单但完美的解决方案:
public static List<Path> listFiles(String rootDirectory)
{
List<Path> files = new ArrayList<>();
listFiles(rootDirectory, files);
return files;
}
private static void listFiles(String path, List<Path> collectedFiles)
{
File root = new File(path);
File[] files = root.listFiles();
if (files == null)
{
return;
}
for (File file : files)
{
if (file.isDirectory())
{
listFiles(file.getAbsolutePath(), collectedFiles);
} else
{
collectedFiles.add(file.toPath());
}
}
}
Java 8提供了一个很好的流来处理树中的所有文件。
try (Stream<Path> stream = Files.walk(Paths.get(path))) {
stream.filter(Files::isRegularFile)
.forEach(System.out::println);
}
这提供了一种自然的遍历文件的方法。因为它是一个流,你可以对结果做所有漂亮的流操作,如限制,分组,映射,退出等。
更新:我可能会指出还有文件。find使用一个BiPredicate,如果需要检查文件属性,这可能更有效。
Files.find(Paths.get(path),
Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile())
.forEach(System.out::println);
注意,虽然JavaDoc回避了这个方法可能比Files更有效。Walk实际上是相同的,如果您也在过滤器中检索文件属性,则可以观察到性能上的差异。最后,如果需要筛选属性,请使用Files。find,否则使用Files。步行,主要是因为交通超载,而且更方便。
测试:根据要求,我提供了许多答案的性能比较。查看包含结果和测试用例的Github项目。
Kotlin为此使用了FileTreeWalk。例如:
dataDir.walkTopDown().filter { !it.isDirectory }.joinToString("\n") {
"${it.toRelativeString(dataDir)}: ${it.length()}"
}
将生成给定根下所有非目录文件的文本列表,每行一个文件,其路径相对于根和长度。
public static String getExten(String path) {
int i = path.lastIndexOf('.');
if (i > 0) {
return path.substring(i);
}
else return "";
}
public static List<String> GetAllFiles(String path, List<String>fileList){
File file = new File(path);
File[] files = file.listFiles();
for(File folder:files) {
if(extensions.contains(getExten(folder.getPath()))) {
fileList.add(folder.getPath());
}
}
File[] direcs = file.listFiles(File::isDirectory);
for(File dir:direcs) {
GetAllFiles(dir.getPath(),fileList);
}
return fileList;
}
这是一个简单的递归函数,应该会提供所有文件。Extensions是一个字符串列表,它只包含那些被接受的扩展名。例如扩展名= [".txt",".docx"]等。
具有单个列表的非递归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);
}
}