一、前言
在操作文件时,我们可能会遇到这样的情况:并不是需要所有的文件,而是只需要满足特定要求的文件。
在遇到这种情况时,如果没有学习文件过滤器,最开始想到的可能是在遍历时,对每一个文件的文件名进行判断,只获取满足要求的文件。
然而,在我们学习了文件过滤器之后,就会发现这样的做法虽然可行,但代码的可重用性低且不灵活。
二、需求
在G:
盘下有一个test文件夹,其内容如下:
1 | G:\test\abc.java |
需求:打印出后缀为java的文件(忽略大小写)
三、未使用文件过滤器
输出所有文件:
1 | public class Demo01 { |
测试结果为:
1 | G:\test\abc.java |
对文件后缀进行判断,只输出满足要求的文件:
1 | public class Demo01 { |
测试结果为:
1 | G:\test\abc.java |
四、使用文件过滤器
(一)简单介绍
1、接口
一共有两个接口可供使用:
1 | Interface FileFilter |
两个接口都只有一个accept()方法,但是它们的参数稍微有点不同:
FileFilter:
1 | boolean accept(File pathname); |
FilenameFilter:
1 | boolean accept(File dir, String name); |
参数具体含义稍后介绍。
2、原理介绍
要弄懂原理,其实我们只需要知道对于接口中的accept()方法被谁调用、如何使用过滤即可。
被谁调用:因为Filter对象是要传递给listFiles()方法的,因此accept()的调用者是listFiles()方法;
如何实现过滤:在accept()方法中编写过滤要求即可,满足要求返回true,反之,返回false。
整体步骤如下:
a. listFiles()方法会先获取指定目录下的所有文件/文件夹(封装为File对象);
b. 遍历每一个File对象,然后作为参数传递给Filter的accept()方法;
c. 在accept()方法中,根据我们编写的代码来判断当前File对象是否满足要求,满足返回true,否则返回false;
d. 在listFiles()方法中,如果收到返回结果为true,将该满足要求的File对象加入到File[]数组中;
e. 都通过accept()方法判断完之后,以File[]数组的形式返回所有满足要求的File对象。
知道了原理之后,我们就能很好的理解accept()方法中的参数含义了:
FileFilter:
1 | boolean accept(File pathname); |
FilenameFilter:
1 | boolean accept(File dir, String name); |
下面通过案例代码来解释:
(二)使用实现类
因为FileFilter和FilenameFilter都是接口,所以我们在使用时必须编写实现类或者编写匿名内部类。
先看实现类的方式:
1 | public class MyFileFilter implements FileFilter { |
1 | public class Demo02 { |
测试结果:
1 | G:\test\abc.java |
该种方式可重用性高,还有需要判断的地方直接使用该过滤器即可。
但是,有时我们只需要使用一次,这个时候会应该考虑匿名内部类的方式了。
(三)使用匿名内部类
1 | public class Demo03 { |
测试结果同上。
(四)使用Lambda表达式
因为这里的两个接口都是只有一个抽象方法,所以我们可以使用Lambda表达式来简化代码:
1 | public class Demo04 { |
并且此处的Lambda表达式还可以进一步简化:
1 | File[] files = dir.listFiles( |
五、补充
前面已经总结了FileFilter的基本使用,虽然没总结FilenameFilter的使用,但其实它们非常的相似,所以使用方式也是大差不差。
因此,只在这里补充一种匿名内部类的方式(其它的方式仿照使用即可):
1 | public class Demo05 { |
六、总结
FileFilter、FilenameFilter不仅使用简单,而且还能有效提高代码可重用性,推荐使用;
Lambda方式使用过滤器更是非常简洁,非常推荐!
Java新手,若有错误,欢迎指正!