递归
递归是一种常见的算法,它可以完成循环做不到的事情,也能做到循环可以做到的事情。缺点是它比循环更加消耗栈内存中的方法临时执行空间,所以能用循环就不用递归。
一个文件夹如果想做删除其实并不简单,它需要遍历到该文件夹中所有的子元素,而我们知道Java中File类的delete()方法是无法删除非空文件夹的,当一个文件夹摆在我们面前,我们根本无法确定里面究竟套了多少个文件夹和文件,因此使用循环想要删除一个文件夹中所有的文件是不可能完成的,因此只能采用递归。
我相信对于绝大多数人来说,递归的基本思想都能理解,但是递归方法写起来还是需要多加用心,最关键还是递归结束的条件如何写,如果结束的条件没有写对,就极有可能会产生栈内存溢出的错误。
遍历文件夹
目标:遍历E盘下的test文件夹下所有文件和文件夹:
test文件夹的文件层级结构:
public class NewTestFile {
/**
* 用来打印出遍历到的文件或文件夹的绝对路径
* @param file 代表文件或文件夹
*/
public void showFile(File file){
//判断如果file是一个文件夹,文件夹内有元素,找一个人先做
File[] files = file.listFiles();//获取file的子元素
//
/**
* 必须使用短路与:&&,先判断file!=null,
* 如果为空,后面那个条件不用判断,直接false,
* 避免空指针异常
*/
if (files!=null && files.length!=0){
for (File f:files){
this.showFile(f);
}
}
//当file是一个文件或一个空的文件夹,就打印它的绝对路径
System.out.println(file.getAbsolutePath());
}
public static void main(String [] args){
File file = new File("E:\\test");
NewTestFile ntf = new NewTestFile();
ntf.showFile(file);
}
}
执行结果:
由于打印输出的语句System.out.println(file.getAbsolutePath());放在了递归方法的最后一行,所以文件树的遍历顺序是这样的:
如果打印输出的语句System.out.println(file.getAbsolutePath());放在了递归方法的的一开始,也就是刚开始就打印那个file的绝对路径,然后再递归找寻它的子元素,那么打印输出的顺序是这样的:
对应于执行结果:
E:\test
E:\test\dirc
E:\test\dirc\aaa
E:\test\dirc\aaa\innera
E:\test\dirc\aaa\innera\innera.txt
E:\test\dirc\aaa\innera\innerinnera
E:\test\dirc\aaa\innera\innerinnera\innerinnera.txt
E:\test\dirc\aaa\inneraa
E:\test\dirc\aaa\inneraa\inneraa.txt
E:\test\dirc\aaa\inneraaa
E:\test\dirc\bbb
E:\test\dirc\bbb\b
E:\test\dirc\bbb\b\1.txt
E:\test\dirc\bbb\b\2.txt
E:\test\dirc\bbb\bb
E:\test\dirc\bbb\bb\11.txt
E:\test\dirc\bbb\bb\22.txt
E:\test\dirc\bbb\bbb
E:\test\dirc\ccc
E:\test\dirc\ccc\cc.txt
E:\test\dirc\ccc\innerc
E:\test\dirc\ccc\innerc\c.txt
E:\test\dirc\ccc\innerc\cc.txt
E:\test\dirc\ccc\innerc\ccc.txt
E:\test\Test.txt
可以看出打印的顺序是类似于树的深度优先遍历的。
删除文件夹
File类提供的delete(File file)方法无法直接删除非空的文件夹,它一次只能删除单个文件或单个空文件夹。
使用刚才的文件夹递归遍历,稍微改动代码,即可完成整个非空文件夹的删除。
比如我们删除刚才的E盘下test文件夹:E:\test
注意:File类的delete()方法是不会把删除的文件放进回收站的,它会直接永久性得删除,找不回来的,所以谨慎操作
/**
* 用来删除一个文件夹
* @param file 代表文件或文件夹
*/
public void deleteFile(File file){
//判断如果file是一个文件夹,文件夹内有元素,找一个人先做
File[] files = file.listFiles();//获取file的子元素
//
/**
* 必须使用短路与:&&,先判断file!=null,
* 如果为空,后面那个条件不用判断,直接false,
* 避免空指针异常
*/
if (files!=null && files.length!=0){
for (File f:files){
this.deleteFile(f);
}
}
//当file是一个文件或一个空的文件夹,就删除它
file.delete();
}
public static void main(String [] args){
File file = new File("E:\\test");
NewTestFile ntf = new NewTestFile();
ntf.deleteFile(file);
}
可以看到test文件夹已经被删除了: