黑马程序员技术交流社区

标题: 【上海校区】文件FileFilter过滤器源码分析 [打印本页]

作者: 小影姐姐    时间: 2018-5-11 11:31
标题: 【上海校区】文件FileFilter过滤器源码分析

文件过滤器介绍


过滤器:它就是把不需要的过滤出去,留下需要的内容。

文件或文件夹过滤器:过滤掉不需要的文件或文件夹,留下需要的文件或文件夹。

有种需求可以考虑使用过滤器:

假设在一个父目录文件夹下有成千上万个文件或者文件夹,而后缀名为.jpg的文件只有几个,我想把后缀名为.jpg的文件找出来,其实使用list()和listFiles()函数可以解决,但是比较麻烦,主要是麻烦在某个类中或者某个项目中写完之后想要在其他项目使用,还得书写,也就是可移植性不是太好,那么我们是否可以想出一个可移植性好的办法呢,写完一次,其他地方可以再用,提高效率简化代码开发。

答案是可以的,过滤器就可以实现。

FileFileter介绍


FileFilter:它也是一个过滤器,专门用来过滤文件或文件夹的。

File类中的函数:

File[] listFiles(FileFilter filter)  返回符合过滤器条件的所有儿子的File数组

FileFilter过滤器中的accept方法中的pathname是当前需要过滤的那个文件或文件夹对象。

或者可以这么理解pathname:就是某个儿子的File对象。

需求:判断D:\test下是否有.jpg文件,如果有,则打印其绝对路径。

分析和步骤:

1)创建测试类FilenameFilterDemo1;

2)在FilenameFilterDemo1类中main函数中创建父目录File类的对象parent,"D:\test"作为函数的参数;

3)使用对象parent调用listFiles()函数获取所有符合条件的儿子的File数组files,自定义过滤器类的对象new MyFilenameFilter()作为参数;

4)循环遍历数组files,获取每个儿子file;

5)使用file对象调用getAbsolutePath()函数获得D:\test文件夹下含有文件.jpg的绝对路径,输出并打印;

测试类代码:

    package cn.itcast.sh.file.filter.demo;
    import java.io.File;
    /*
     * 演示文件过滤器 FileFilter
     * 需求:判断D:\\test下是否有.jpg文件,如果有,则打印其绝对路径。
     */
    public class FileFilterDemo {
            public static void main(String[] args) {
                    // 创建父目录D:\\test的对象
                    File f = new File("D:\\test");
                    File[] arr = f.listFiles(new MyFileFilter(".jpg"));
                    for (File file2 : arr) {
                            //输出绝对路径
                            System.out.println(file2.getAbsolutePath());
                    }
            }
    }

过滤器类代码实现:

说明:对FileFilter接口中的accept函数进行进一步说明:

这个方法中定义过滤条件,当我们调用listFiles方法的时候,会把每个儿子都拿来调用accept方法:

         如果这个方法返回true,那么这个儿子会被添加到最终的数组中

         如果这个方法返回false,那么这个儿子就不会被添加到最终的数组

1)创建一个过滤器类MyFileFilter 并实现FileFilter接口,然后复写接口中的accept()函数;

2)在accept函数定义过滤条件来判断每个儿子是否符合要求,符合就返回true,否则返回false;

3)使用File类的对象pathname调用getName()然后调用String类中的endsWith()函数判断文件名的后缀名是否是.jpg;

4)使用File类的对象pathname函数调用isFile()判断是否是文件;

5)使用return关键字将上述两个布尔类型的值返回;

    package cn.itcast.sh.file.filter.demo;
    import java.io.File;
    import java.io.FileFilter;
    /*
     * 自定义文件过滤器
     */
    public class MyFileFilter implements FileFilter {
              //定义成员变量
              private String suffix;
              public MyFileFilter(String suffix)
        {
                      this.suffix=suffix;
            }
            public boolean accept(File pathname) {
                    boolean boo = pathname.isFile();
                    String name = pathname.getName();
                    //判断字符串name的后缀名是否是.jpg
                    boolean boo2 = name.endsWith(suffix);
                    return boo && boo2;
            }
    }

过滤器源码实现

上述我们使用了过滤器,那么关于过滤器FileFilter中的accept什么时候来调用的,我们现在需要查看listFiles的源代码。

源代码整体解释如下图所示:



1)

    f.listFiles(new MyFileFilter(".jpg"));

表示使用File类的对象调用listFiles方法,并且自定义过滤器MyFileFilter类的对象作为参数传递。

2)

    public File[] listFiles(FileFilter filter) {
            String ss[] = list();
            if (ss == null) return null;
            ArrayList<File> files = new ArrayList<>();
            for (String s : ss) {
                File f = new File(s, this);
                if ((filter == null) || filter.accept(f))
                    files.add(f);
            }
            return files.toArray(new File[files.size()]);
        }

FileFilter filter = new MyFileFilter(".jpg").所以这里filter 就表示过滤器对象。

String ss[] = list(); 表示列出父目录下所有的子文件或者子文件存储到ss数组中。

if (ss == null) return null;判断数组是否等于null,如果等于null,则返回给调用者null,结束整个listFiles方法。

ArrayList<File> files = new ArrayList<>();

表示创建一个空的集合来存储满足条件的子文件。

for (String s : ss) {....} 遍历指定父目录下的所有子文件或者子文件夹

File f = new File(s, this);

这里的s表示指定父目录下的子文件或者子文件夹。而this表示当前对象即调用该方法的对象,就是f,父目录。

     if ((filter == null) || filter.accept(f)){files.add(f);}

判断过滤器是否为null,由于这里传递的过滤器不是null,所以 filter == null 为false,继续执行双或后面的内容:

    filter.accept(f)

这里调用了accept方法:

    public class MyFileFilter implements FileFilter {
              //定义成员变量
              private String suffix;
              public MyFileFilter(String suffix)
        {
                      this.suffix=suffix;
            }
            public boolean accept(File pathname) {
                    boolean boo = pathname.isFile();
                    String name = pathname.getName();
                    //判断字符串name的后缀名是否是.jpg
                    boolean boo2 = name.endsWith(suffix);
                    return boo && boo2;
            }
    }

当accept方法返回true的时候,那么就执行上述的代码:

files.add(f);

向集合中添加满足条件的子文件。

return files.toArray(new File[files.size()]);

表示将存储满足条件的集合转换为数组,返回给调用者:

    File[] arr = f.listFiles(new MyFileFilter(".jpg"));










1.png (22.01 KB, 下载次数: 6)

1.png





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2