通过递归的方法输出目录下的所有文件路径时 文件路径输出顺序异常
提示:此问题根本原因很简单,过程分析较为繁杂,想直接看原因的童鞋可以跳到最后结论部分。
关键词
File类、递归、listFiles()方法 、路径输出异常
摘要
本篇文章讨论了在通过递归的办法输出一个目录(文件夹)时,递归输出文件路径没有按照正常预期的递归顺序输出文件路径的现象,并对该问题的出现做了相关的分析讲解。所谓的递归的文件路径没有按照正常的预期递归顺序输出,即在控制台输出的第一个文件的文件名称并非是递归遇到的第一个文件的路径。这样解释仍然有些拗口,具体我们通过下面的图文进行解答。
问题解释
暂时不讲代码部分,先来看问题解释
1.假设现在我们有一个目录FileTest
2.在该目录下还有两个目录File Client、File Server
3.在File Server目录下没有任何文件及目录,在File Client只有两个目录和一个文件,如下图所示
4.File Client下的第一个目录docs下只有一个文件fzdefaults.xml.example
熟悉递归原理的小伙伴应该都知道,在此案例中,递归第一个遇到的文件的过程应该是FileTest—>File Client—>docs—>fzdefaults.xml.example,因为fzdefaults.xml.example才是第一个目录递归下去遇到的第一个文件,按照预期第一个输出的文件路径应该为fzdefaults.xml.example此文件的路径,然而控制台输出的第一个文件路径却是AUTHORS,如下图;很明显AUTHORS文件并非第一个目录递归下去遇到的第一个文件,这便是文章所说的问题。那么是什么导致了这种情况的产生呢?接下来让我们深入探讨问题来龙去脉。
我们通过一个简单的题目进行此案例的相关演示,题目信息如下。
题目要求
输出一个目录下的所有文件的路径,通过递归实现。
给定目录样例
目录样例就是我们上面提到的目录,所有目录、文件都没变。
题目分析
思路:对每一级目录进行遍历,然后继续遍历上一次遍历得到的目录,非目录(即文件)则输出,目录为空作为递归结束条件。
首先我们需要在main方法中定义一个srcFile对象,用来获取目录;接着,通过递归实现,那么我们就要定义该递归方法,假设定义了一个方法public static void getAllFilePath(File File);该方法体实现思路如下:
- 通过listFile()方法返回当前File目录的所有文件信息;
- 判断当前目录下内容是否为空,是,return返回(递归出口);
- 不为空,通过增强for获取到当前File目录下的每一个文件或目录;
- 增强for内部判断当前获取到的是否为目录;
4.1 是,继续调用递归方法自身;
4.2 否,输出当前文件的路径;
代码实现
实现的代码如下;
import java.io.File;
//输出问价目录下的所有文件的绝对路径
//通过递归实现
public class MainTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
File srcFile = new File("E:\\FileTest");
getAllFilePath(srcFile);
}
public static void getAllFilePath(File File) {
File[] listFiles = File.listFiles();
// 递归出口
if(listFiles==null)
return ;
else {
for(File file : listFiles) {
// 判断是否是目录 是 继续递归
if(file.isDirectory()) {
getAllFilePath(file);
}
// 否 输出路径
else {
System.out.println(file.getAbsolutePath());
}
}
}
}
}
输出
问题分析
通过代码我们可以看到,既然每一次都是通过目录进行遍历的,那么一级一级地遍历下去,我们得到的第一个文件必然是第一个目录下的第一个目录下的第一个目录下的…第一个文件;我们先给出整个目录的图示信息,如下所示。
按照递归遍历的基本思路,一级一级遍历目录,那么第一个输出的文件应该是上图所示的文件2,具体递归的过程分析如下图。
问题解析
从一级目录作为递归入口,每次都对第一个目录进行此递归流程判断,一级目录递归到二级二级目录,二级目录递归到三级目录,重点来了!!!
以下解释问题发生的具体原因:此时三级目录下有一个文件AUTHORS,按理来说,三级目录下还有两个目录,这两个目录还没有被递归进入判断,为什么程序这时直接输出AUTHORS文件了呢?这就要不得不提到listFiles()方法的内部原理了,通过查询Java手册,我没有查到listFiles()方法的详细解释,但是通过笔者的实验最终分析得到了listFiles()方法的具体实现原理。
原理分析
- 原理分析
listFiles()方法的作用是将一个目录下所有内容(包括子目录和子文件)的名称添加到一个File集合中,但是,该集合的创建并不是像我们所想的那样直接把目录下的内容从上到下录入File集合的!而是类似于重写了自然排序的方法,使数据在添加到集合的过程中,按照一定的顺序排列的,在此listFiles()方法中,它达到的最终结果就是使文件录入到集合时按照字母的顺序添加到集合的(不区分文件还是目录)。因此在第三级递归时,listFiles()得到的集合应该是这样的,[AUTHORS,docs,locales],于是第一个判断的就是AUTHORS文件了,然后就直接输出了,而不是按照我们在电脑中创建的顺序进行递归遍历的!
好了,本篇文章关于递归的方法输出目录下的所有文件路径时,遇到的文件输出顺序未按预期输出的现象的分析到这里就结束了,感谢您的观看,如有疑问的地方欢迎在评论区留言!