文件过滤器的使用

文件过滤器的作用:在众多的文件中,筛选出符合条件的文件.例如在我的电脑中的,D:\文档\浏览器下载目录下,筛选出所有的以.exe或者.pdf等等结尾的文件

在java中,专门提供了文件过滤器接口.

public interface FilenameFilter    accept(File dirs,String name)

public interface FileFilter       accept(File pathname);

这两个过滤器中,实现文件过滤功能的函数正是accept,接口中也只有一个函数.

在使用时,要对过滤器接口进行实现

区别:

FilenameFilter中的accept函数接收的是两个参数:指定父目录的路径和父目录路径中所有的子文件或者子文件夹,需要将这两个参数封装成File的对象再使用File中的功能

FileFilter中的accept函数接收的则直接是:完整的路径,即需要进行过滤操作的文件或文件夹,直接可以使用File中的功能

要想完成过滤功能,同时还需要File类中的两个函数:

1)public String[] list(FilenameFilter filter)  将满足过滤器条件的以数组形式返回

2)public File[] listFiles(FilenameFilter filter)  将满足过滤器条件的以File对象数组的形式返回

 1     public String[] list(FilenameFilter filter) {
 2         String names[] = list();
 3         if ((names == null) || (filter == null)) {
 4             return names;
 5         }
 6         List<String> v = new ArrayList<>();
 7         for (int i = 0 ; i < names.length ; i++) {
 8             if (filter.accept(this, names[i])) {
 9                 v.add(names[i]);
10             }
11         }
12         return v.toArray(new String[v.size()]);  //从源代码中可以看到,list返回的是一个string类型的数组,而listFile返回的是File对象数组(下面可以看到)
13     }

从源代码中可以看到,list返回的是一个String类型的数组,而listFiles返回的是File对象数组(在下面会附源代码)

这两个函数的参数也可以是(FileFilter filter),操作更为简单

以FilenameFilter为例,分别使用list和listFiles()

1 public boolean accept(File dir, String name) {
2         //先判断是否以.exe后缀结尾
3         boolean matched = name.endsWith(".exe");
4         //将dir和name封装成一个File对象,再使用File中的功能
5         File f = new File(dir,name);
6         boolean isFile = f.isFile();
7 
8         return matched && isFile;
9     }

主函数中:

 1 public static void main(String[] args) {
 2         //创建父目录File类的对象parent
 3         File parent = new File("D:\\文档\\浏览器下载");
 4         //创建文件过滤器的对象
 5         MyFilenameFilter my = new MyFilenameFilter();
 6         method_1(parent, my);
 7 
 8     }
 9 private static void method_1(File parent, MyFilenameFilter my) {
10         //使用parent调用list.返回的是子文件或者子文件夹,下面需要封装
11         String[] names = parent.list(my);
12         for(String name : names){
13             //System.out.println(name);
14             File file = new File(parent,name);
15             String path = file.getAbsolutePath();
16             System.out.println(file);
17             System.out.println(path);
18         }
19     }

如果使用listFile()的话,返回的直接是满足条件的文件对象数组

 1     private static void method_2(File parent, MyFilenameFilter my) {
 2         //使用parent调用listfiles,返回的是File对象数组,下面不需要封装
 3         File[] names = parent.listFiles(my);
 4         for(File name : names){
 5             File path = name.getAbsoluteFile();
 6             System.out.println(name);
 7             System.out.println(path);
 8         }
 9         
10     }

如果使用FileFilter的话

1 public boolean accept(File pathname) {
2         //pathname是一个File对象,可以直接调用File中的功能
3         boolean matched = pathname.getName().endsWith(suffix);
4         boolean isFile = pathname.isFile();
5         return matched && isFile ;
6     }
 1     public static void main(String[] args) {
 2         //创建父目录File类的对象parent
 3         File parent = new File("D:\\文档\\浏览器下载");
 4         //创建文件过滤器的对象
 5         MyFileFilter fileFilter = new MyFileFilter();
 6         method_3(parent, fileFilter);
 7 
 8     }
 9 
10     private static void method_3(File parent, MyFileFilter fileFilter) {
11         //
12         File[] names = parent.listFiles(fileFilter);
13         for(File name : names){
14             System.out.println(name);
15         }
16     }

以上便是我们要使用过滤器的话,需要实现的代码.

那么问题又来了,accept函数到底是什么时候被调用执行的呢?这个和底层的源代码有关.

1     public File[] listFiles(FilenameFilter filter) {
2         String ss[] = list();
3         if (ss == null) return null;
4         ArrayList<File> files = new ArrayList<>();
5         for (String s : ss)
6             if ((filter == null) || filter.accept(this, s))  //accept的主要区别在这.accept需要接收两个参数,并由我们手动完成封装
7                 files.add(new File(s, this));
8         return files.toArray(new File[files.size()]);
9     }
 1    public File[] listFiles(FileFilter filter) {
 2         String ss[] = list();
 3         if (ss == null) return null;
 4         ArrayList<File> files = new ArrayList<>();
 5         for (String s : ss) {
 6             File f = new File(s, this);  //底层自动帮我们对s和this进行了封装,最后accept只需要接收一个File对象就可以了
 7             if ((filter == null) || filter.accept(f))
 8                 files.add(f);
 9         }
10         return files.toArray(new File[files.size()]);
11     }

为了便于理解,我下面上传一张图片来演示底层的调用

注意辣:如果给定的parent(一开始指定的)的文件目录是有问题的,那么就会出现空指针异常.

 这样的话,调用过程就比较清晰了.

最后,把程序改进以下,使得可以根据用户的需求,更改筛选的目标,使可以筛选不同后缀名的文件.

可以通过文件过滤器的构造函数来传递这个表示后缀的参数

 1 public class MyFileFilter implements FileFilter{
 2     public String suffix;
 3     MyFileFilter(String suffix){
 4         this.suffix = suffix;
 5     }
 6     
 7     @Override
 8     public boolean accept(File pathname) {
 9         //
10         boolean matched = pathname.getName().endsWith(suffix);
11         boolean isFile = pathname.isFile();
12         return matched && isFile ;
13     }
14 
15 }
1 public static void main(String[] args) {
2         //创建父目录File类的对象parent
3         File parent = new File("D:\\文档\\浏览器下载");
4         //创建文件过滤器的对象
5         MyFileFilter fileFilter = new MyFileFilter(".exe");  //在创建对象的时候传递suffix的参数就可以了
6     }

 以上关于文件过滤器的理解已经比较透彻了.

总结一下吧:

可以使用FilenameFilter 和FileFilter过滤器,两者中的accept函数所需要的参数不一样,对应的操作也不一样,FilenameFilter的accept需要两个参数,而FileFilter的则是File对象

list(FilenameFilter filter)  返回的是string数组,其中存的就是满足过滤器条件的子文件或者子文件夹

listFiles(FilenameFilter/FileFilter filter)  返回是对象数组,存的是满足过滤器条件的File对象

猜你喜欢

转载自blog.csdn.net/worisaa/article/details/64124217