Java基础进阶  IO介绍之File类、文件过滤器

1、IO介绍

在前期的学习上述知识点的过程中,我们书写的任何程序,它运行的时候都会有数据的产生,比如时间数据,而这些数据最终都保存在内存中。程序运行结束之后,数据就没有了。当程序下次启动的时候,如果还需要使用上次的结果,这时程序中是没有的。

而在开发中,在我们真正书写的程序中,往往有一些数据是需要长久保存起来的,当程序中需要这些长久保存起来的数据的时候,再从其他的地方读取到程序中。

也就是说我们以前学习的数据都是存储到内存中,而内存中只能暂时存储数据,当电脑关闭之后,数据就不见了。如果在开发中需要大量数据被长久保存,下次开电脑这些数据仍然还在,那么我们肯定不能保存到内存中,我们需要保存在能够保存持久数据的地方或者叫持久设备。

那么问题来了:什么是持久设备呢?

1.1什么是持久设备

持久设备:可以持久保存数据的设备。硬盘、U盘、光盘、网盘、软盘等。这些设备都可以长久的保存数据。
那么还有一个问题:如何把程序中的数据保存到持久设备中?
Java提供了一个技术,专门来实现数据与持久设备间的交互:IO技术。
通过IO技术就可以达到程序和其他设备之间的数据交互。

1.2什么是IO技术

IO技术:它主要的功能就是把我们程序中的数据可以保存到程序以外的其他持久设备中(如:我们电脑的硬盘),或者从其他持久设备中(如:我们电脑的硬盘)进行读取数据,把数据读取到我们的Java程序中。
IO:
I:Input:输入或者读取,从持久设备(硬盘)的数据放到内存中;
O:Output:输出或者写出,从内存中的数据放到持久设备(硬盘)上;

也可以按照如下理解:
把从持久设备(硬盘)上读取(输入)到内存中的动作,称为读操作。 I:input。
把内存中的数据输出(写出)到持久设备(硬盘)的动作,称为写操作。O:output。

读写操作图解如下所示:


1.png

说明:
1)我们的程序运行在内存中,因此我们的输入和写出都是相对内存而言;
2)Java程序必须运行在Java虚拟机上,Java程序最终需要JVM来执行;
3)JVM属于应用软件需要安装在操作系统软件上,所以JVM虚拟机是运行在操作系统之上的,然后由操作系统和计算机硬件进行交互;

2、File类

2.1、File类介绍

数据最终保存在硬盘上,在硬盘上是以1和0 保存的。而给我们展示出来的并不是二进制数据,而是一个一个的文件,换句话说数据最终都保存在这些文件中。而这些文件又被文件夹管理。
通过上述描述我们发现在计算机硬盘中就存在两种事物:文件和文件夹事物。而在Java中使用class类来描述生活中存在的事物,那么Java中是如何描述文件和文件夹这两类事物呢?

使用File类来描述文件和文件夹事物。


2.png

说明:
1)Java中的定义的io技术的类基本都在java.io包下;
2)使用File类来描述文件和文件夹事物的;
3)File类它主要是对持久设备上的文件和文件夹进行操作。它不能去操作文件中的数据。将来我们只要需要操作持久设备上的文件或文件夹直接找File类完成,如果要操作文件中的数据只能找后面学习的IO技术搞定;

结论:File类就是描述文件或文件夹的,只要我们在Java中要操作文件或文件夹,就找File类。

2.2、File类构造方法

3.png

1)public File(String pathname) 表示根据文件或文件夹的路径名创建一个File对象。
使用File类的构造函数可以把指定的字符串封装成File类的对象,但是这个字符串表示的路径或者文件到底是否存在,File类是不进行判断的。
注意:File类表示文件和目录路径名的抽象表示形式。那么该路径代表的文件或文件夹不一定存在。

需求:创建一个File类的对象,表示:D:\abc\1.txt


4.png

2)public File(String parent,String child) 根据父目录的路径名和儿子的名称创建一个File对象。

创建是儿子的对象
需求:创建一个File类的对象,表示:D:\abc\1.txt


5.png

3)public File(File parent,String child) 根据父目录的File对象和儿子的名称创建一个File对象。
就是把已经存在的File对象和某个子目录合并成一个新的File对象。
分析和步骤:
A:创建一个File类的对象parent,D:\abc作为参数;
B:定义一个字符串child=1.txt;
C:使用上述构造函数在重新创建一个File类的对象file,并输出打印;


6.png

2.3、获取方法

File类是描述文件和文件夹的。使用File类的对象就可以获取当前File类描述的那个文件或文件夹的信息(信息包括文件或者文件夹的名称、大小、类型、日期等)。

案例:File类中的获取方法。
A:getAbsolutePath() 获取的当前调用这个方法的File对象的全路径(绝对路径或者真实路径) 返回的是路径的字符串;
B:getAbsoluteFile()获取的当前调用这个方法的File对象的全路径(绝对路径或者真实路径) 返回的是路径封装成的新的File;

说明:在操作文件时,需要指定文件的路径,而路径在程序中有两种表现形式:
1、 绝对路径(真实路径):是从盘符开始的路径,带有根目录的路径 例: D:\abc\test\Demo.java D就是根目录。
2、 相对路径:是从当前路径开始的路径,或者可以理解不带根目录的路径
例: 当前路径为D:\abc,要描述相对路径,只需输入test\Demo.java
实际上,严格的相对路径写法应为: .\test\Demo.java
其中,. 表示当前路径。
C:getName() 获取的是File类的对象中封装的文件或目录的最后一级名称;
D:getParentFile() 获取到的是File类的对象的父目录,把父目录封装成一个新的File对象;
E:getParent() 获取到File类的对象的父目录,把返回目录的字符串表示形式;
F:getPath() 获取到当前File类的对象中封装的内容;</pre>
G:getFreeSpace() 获取某个盘的剩余空间;
H:getTotalSpace() 获取某个盘的总空间;
I:public static File[] listRoots() 获取系统的所有根目录,例如:C盘、D盘、E盘、F盘;
说明:由于该函数是静态的,直接使用类名调用即可。
获取函数代码演示如下所示:

package cn.xuexi.file.constructor.demo;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
 * File类中的获取方法演示
 * 绝对路径:带根路径
 * 相对路径:不带根路径 test\\haha表示相对路径,这里表示相对于项目day19a来说
 */
public class FileGetFunctionDemo {
    public static void main(String[] args) {
        // 创建File类的对象
        File file=new File("D:\\test\\123.txt");
        //getAbsolutePath()获取绝对路径演示 返回的是路径的字符串 D:\test\123.txt
         //如果File file=new File(""); 参数不指定路径,则输出当前项目的路径F:\newEclipseWorkspace\beike\day19a
        String absolutePath = file.getAbsolutePath();
        System.out.println("absolutePath="+absolutePath);
        //getAbsoluteFile()获取绝对路径演示 返回的是路径新封装的File类的对象 D:\test\123.txt
         //如果File file=new File(""); 参数不指定路径,则输出当前项目的路径F:\newEclipseWorkspace\beike\day19a
        File absoluteFile = file.getAbsoluteFile();
        System.out.println("absoluteFile="+absoluteFile);
        //getName()函数  获取的是封装在File类中的文件或者文件夹的最后一级名称 123.txt
        System.out.println("getName()="+file.getName());
        //getParentFile()函数演示 获得File类中的文件或者文件夹的路径的父目录 封装在在一个File类中D:\test
        System.out.println("getParentFile()="+file.getParentFile());
        //getParent()函数演示 获得File类中的文件或者文件夹的路径的父目录 封装在String类中 D:\test
        System.out.println("getParent()="+file.getParent());
        //getPath()表示获得File类中封装的所有内容 D:\test\123.txt
         //如果File file=new File(""); 参数不指定路径,则输出””空字符串
        System.out.println("getPath()="+file.getPath());
        //getFreeSpace() 函数
         //如果File file=new File("D:\\"); D盘剩余空间是:366774648832
        System.out.println("剩余空间是"+file.getFreeSpace());
        //getTotalSpace() 函数
         //如果File file=new File("D:\\"); D盘总空间是:371056439296
        System.out.println("总空间是"+file.getTotalSpace());
        System.out.println("----------------");
        //调用listRoots()函数获取系统的根目录 由于该函数是静态的,直接使用类名调用即可
         //  输出结果C:\ D:\ E:\ F:\ G:\ H:\ 
        File[] dirs = File.listRoots();
        for (File dir : dirs) {
            System.out.print(dir+” ”);
        }
    }
}

J:public long lastModified() 获取上一次修改的时间,返回的是毫秒值;

演示lastModified函数:
分析和步骤:
1)创建File类的对象file2,D:\test\123.txt作为构造函数的参数;
2)使用对象file2调用lastModified()函数获得上次更改D盘下的123.txt文件的时间time;
3)使用Date()构造函数将time转换成Date时间类的对象d;
4)创建SimpleDateFormat类的对象sdf,时间格式是:yyyy-MM-dd HH:mm:ss;
5)使用格式化解析器对象sdf调用format函数将日期时间对象d转换为字符串sTime,并输出;

获取函数代码演示如下所示:


7.png

2.4、创建方法

由于File类既可以表示文件,也可以表示文件夹(目录)。Java针对File类的创建方法给出2类,一类是创建文件的方法,一类是创建文件夹的方法。

1、创建文件


8.png

可以创建一个文件,返回的boolean值表示文件是否创建成功。
true :表示创建文件成功; false :表示创建文件失败,失败原因基本是因为当前的目录有了相同的文件;
需求:创建:D:\abc\1.txt文件。在D盘的abc文件夹下新创建一个1.txt文件。
分析和步骤:
1)创建File类的对象file,指定目录和文件名;
2)使用file对象调用createNewFile()函数创建文件,并打印返回值;


9.png

说明:
1)createNewFile()函数表示 把封装的File类的对象创建成一个文件,
如果指定的路径没有创建的文件,则会创建文件,返回值是true,创建成功;
如果同名的文件已经存在,则不会再创建文件,返回false,创建失败;
如果指定的路径不存在,这时就会抛异常 Java.io.IOException:系统找不到指定的路径。这时是不会去创建文件的;
2)只要使用createNewFile()函数创建出来的一定是文件,不管有没有扩展名。如果指定的文件没有扩展名,那么也会创建没有扩展名的文件;
补充:在计算机中,一个文件是可以没有扩展名的。
3)创建File类的对象时,如果找不到创建文件的路径就会报上述异常:Java.io.IOException;

2、创建文件夹


10.png

mkdir() 函数表示创建单级目录。如果创建文件夹中存在要创建的文件夹,则返回false,创建失败,
如果创建超过一个目录,也会返回false。前提是这个多级目录在计算机上都没有存在。
如果是多级目录,但是多级目录除了最后一个目录,前面目录都存在,那么也会返回true,创建成功。
mkdirs() 函数表示一次创建多级目录。创建单级目录也可以,如果创建文件夹中存在此文件夹,
则返回false,创建失败。

需求:创建一个多目录文件夹D:\aaa\bbb\ccc
分析和步骤:
1)创建File类的对象file,指定创建的目录;
2)使用file对象分别调用mkdir() 和mkdirs() 函数创建文件夹,并打印返回值;


11.png

需求:使用mkdirs()函数创建一个D:\abc\1.jpg 的文件夹。


12.png

注意:
1):创建文件或文件夹时,一定要调用正确的方法。
骑着白马的不一定是王子,也有可能是唐僧;
长着翅膀的不一定是天使,也有可能是鸟人;
名字叫.jpg的不一定是文件,也有可能是文件夹;

举例:new File(“D:\abc\1.jpg”);
A:如果使用File类的对象创建文件夹,那么在硬盘上就会生成一个文件夹。名字为1.jpg.
而此时如果在使用createNewFile()在创建1.jpg文件,也不会创建成功;
B:注意啦 如果创建文件夹的时候,当前目录中存在一个文件的全名(文件名+后缀名)和要创建文件夹同名,那么也不会创建该文件夹;
举例:比如我要创建:

13.png

结果在D:\abc文件夹下面有一个文件的名字叫做:1.jsp文件名
此时不会创建成功。
2):绝对路径和相对路径创建文件或者文件夹的问题。
绝对路径:有根目录的路径
相对路径:没有根目录的路径
我们创建一个文件或文件夹时,如果使用了相对路径,会在项目目录下创建。

2.5、删除方法

14.png

boolean delete() 删除File类对象中的文件或文件夹。


15.png

注意:
1)delete()函数的删除不走回收站。谨慎使用。
2)delete()函数可以删除文件或者文件夹,但是删除文件夹的时候,要求文件夹一定是空的。也就是说如果一个文件夹中有儿子,那么不能直接删除该文件夹。

2.6、判断方法

File类既可以描述文件,也可以描述文件夹。那么File类中就给出了判断当前File对象封装的对象到底是文件还是文件夹。


16.png
17.png

public boolean isDirectory() 是否是文件夹 如果是文件夹 返回 true 否则返回false;
public boolean isFile() 是否是文件 如果是文件 返回 true , 否则返回false;
public boolean isHidden() 是否隐藏 如果是隐藏文件或者文件夹 返回 true , 否则返回false;
public boolean exists() 是否存在 如果File类对象中的文件或者文件夹在硬盘上存在 返回 true ,否则返回false;

代码演示如下所示:


18.png

2.7、列举方法

有时我们需要获取指定目录下的文件或文件夹。所以我们可以采用以下方法来获取。


19.png

list()它是获取指定目录(文件夹)下的所有文件或文件夹,把这些文件或文件夹的名字保存在返回的字符串数组中。
可以理解为获取当前目录下的所有儿子的名称的数组。

需求:扫描D:\test下的所有子文件和子文件夹,并且打印子文件或者子文件夹名。
分析和步骤:
1):创建父目录D:\test的File对象dir;
2):使用dir对象调用list()函数获取所有儿子的数组,数组名叫做dirs;
3):使用foreach循环遍历dirs,打印数组中存放的文件或者文件夹名;

//需求:扫描D:\\test下的所有子文件和子文件夹,并且打印子文件或者子文件夹名。
    public static void method_1() {
        // 创建File类的对象
        File file = new File("D:\\test");
        //使用file对象调用list()函数所有的儿子文件或者文件夹
        String[] dirs = file.list();
        //循环遍历数组
        for (String dir : dirs) {
            System.out.println(dir);
        }
    }

上述代码结果:
1.jsp
1.mp3
1.txt
123
说明:每个字符串是一个文件名,而不是一条完整路径。也就是说list()函数获取的子文件或者子文件夹的名字。
上述函数虽然可以获得文件或者文件夹名字,但是都变成字符串了,在开发中用处不是太大,我们更希望获得的是文件或者文件夹的对象,这样操作会更广泛。

20.png

listFiles()它也是获取指定目录下的文件和文件夹,但把这些文件和文件夹的名字重新封装成一个一个独立的File对象,把这些File对象保存在File数组中,最后返回这个File数组。
也可以理解为获取当前目录下的所有儿子File对象的数组。
需求:扫描D:\test下的所有子文件和子文件夹,打印出哪些是文件夹哪些是文件。
分析和步骤:
1):创建父目录D:\test的File对象dir;
2):使用dir对象调用listFiles()函数获取所有儿子的对象数组,数组名叫做files;
3):使用foreach循环遍历files,获取每个文件或者文件夹的对象file;
4):使用file对象调用isDirectory()判断此时file对象是否是文件夹,如果是,则打印文件夹,否则说明是文件,打印文件;

//需求:扫描D:\\test下的所有子文件和子文件夹,打印出哪些是文件夹哪些是文件。
    public static void method_2() {
        // 创建File类的对象
        File file = new File("D:\\test");
        //根据file对象调用listFiles()函数获得上述文件夹中的所有儿子文件和文件夹
        File[] dirs = file.listFiles();
        //遍历数组获得File类的对象
        for (File dir : dirs) {
           // System.out.println(dir);
            /*
             * 如果想输出哪些是文件夹哪些是文件,由于File类中要么是文件要么是文件夹
             * 所以我们可以先获得文件夹,然后打印,则另一个就是文件
             * dir.isDirectory() 如果为true,说明是文件夹
             * dir.getName()表示获得文件或者文件夹的名字
             */
            if(dir.isDirectory())
            {
                //说明是文件夹
                System.out.println(dir.getName()+"是文件夹");
            }else
            {
                //说明是文件
                System.out.println(dir.getName()+"是文件");
            }
        }
    }

说明:
1、如果想输出哪些是文件夹哪些是文件,由于File类中要么是文件要么是文件夹。所以我们可以先获得文件夹,然后打印,则另一个就是文件。
dir.isDirectory() 如果为true,说明是文件夹;
dir.getName() 表示获得文件或者文件夹的名字;
2、当使用foreach循环的时候,执行System.out.println(dir);这个代码的时候,打印的结果如下:


21.png

注意:listFiles()函数表示获得的每个路径名都是绝对路径名。

3、文件过滤器(难)

3.1、文件过滤器介绍

过滤器:它就是把不需要的过滤出去,留下需要的内容。
文件或文件夹过滤器:过滤掉不需要的文件或文件夹,留下需要的文件或文件夹。
有种需求可以考虑使用过滤器:

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

3.2、FilenameFilter接口(文件名过滤器)

22.png

accept:方法是用来书写具体过滤的条件的。
dir参数:是当前name所表示的文件或文件夹所在的父目录。
name参数:是需要过滤的那个文件夹的名字或者文件的整体名字(包括文件的后缀名,例如123.java 或者mm.jpg)。

举例:想过滤 D:\test\123.java 下面的123.Java文件,如果想使用这个accept(dir,name)函数,
那么dir 表示D:\test,而name表示123.java。
注意:这个接口没有实现类,如果我们想使用这个接口中的函数,我们需要自己定义实现类并复写accept()函数。

File类中的函数:
public String[] list(FilenameFilter filter) 返回符合过滤器中条件的儿子的名称的字符串数组
public File[] listFiles(FilenameFilter filter) 返回符合过滤器中条件的儿子的File对象数组

需求:判断D:\test下是否有.jpg文件,如果有,则打印其绝对路径。
分析和步骤:
1)创建测试类FilenameFilterDemo;
2)在FilenameFilterDemo类中main函数中创建父目录File类的对象parent,"D:\test"作为函数的参数;
3)使用对象parent调用list()函数获取所有符合条件的儿子的名称数组names,自定义过滤器类的对象new MyFilenameFilter()作为参数;
4)循环遍历数组names,获取每个儿子;
5)创建File类的对象重新封装儿子的对象file;
6)使用file对象调用getAbsolutePath()函数获得D:\test文件夹下含有文件.jpg的绝对路径,输出并打印;
7)上述方案也可以换另一种方式实现,父目录对象可以调用listFiles()函数来获得符合过滤器中条件的儿子的File对象数组;
使用public String[] list(FilenameFilter filter) 函数方式来实现过滤功能。

测试类代码如下:

package cn.xuexi.file.filter.demo;
import java.io.File;
/*
 * FilenameFilter过滤器的演示
 * 需求:判断D:\\test下是否有.jpg文件,如果有,则打印其绝对路径。
 */
public class FileNameFilterDemo {
    public static void main(String[] args) {
        method_1();
    }
    //  public String[] list(FilenameFilter filter) 返回符合过滤器中条件的儿子的名称的字符串数组
    public static void method_1() {
        // 创建File类的对象
        File file = new File("D:\\test");
        /*
         * 使用file对象调用list(FilenameFilter filter) 函数来筛选D:\\test
         * 目录下儿子文件后缀名是.jpg
         */
        //获得符合条件的儿子的名字的数组
        String[] names = file.list(new MyFilenameFilter());
        //遍历数组
        for (String name : names) {
            /*
             * 这里的name就是表示D:\\test目录下符合条件的儿子的名字
             * 也就是说name在这里就是所有后缀名为.jpg的文件名字
             * 如D:\\test目录下的1.jpg文件
             * 由于题目需求是想获得儿子文件的绝对路径
             * 想获得绝对路径必须得调用File类中的getAbsolutePath()函数
             * 而这个函数是非静态函数得通过File的对象调用
             * 所以接下来我们要获得File类的对象
             */
            //使用File类的构造函数封装儿子的对象 file2代表后缀名是.jpg的文件的对象
            File file2 = new File(file,name);
            System.out.println(file2.getAbsolutePath());
        }
    }

过滤器类代码实现:
说明:对FilenameFilter接口中的accept函数进行进一步说明:
这个方法中定义过滤条件,当我们调用list或者listFiles方法的时候,会把每个儿子都拿来调用accept方法:
如果这个方法返回true,那么这个儿子会被添加到最终的数组中;
如果这个方法返回false,那么这个儿子就不会被添加到最终的数组;
1)创建一个过滤器类MyFilenameFilter 并实现FilenameFilter接口,然后复写接口中的accept()函数;
2)在accept函数定义过滤条件来判断每个儿子是否符合要求,符合就返回true,否则返回false;
3)创建File类的对象封装儿子的对象file;
4)定义一个boolean类型的变量flag来接收name的后缀名是否是.jpg,并且必须是文件的布尔值;
5)返回flag的值;

package cn.xuexi.file.filter.demo;
import java.io.File;
import java.io.FilenameFilter;
/*
 * 过滤名字的过滤器
 */
public class MyFilenameFilter implements FilenameFilter{
    public boolean accept(File dir, String name) {
        /*
         * 我们需要在这里书写过滤条件,判断儿子是否符合条件
         * 符合,则返回true
         * 不符合,则返回false
         * dir表示父目录
         * name 表示儿子(文件或者文件夹)的名字 例如 1.jpg
         */
        //输出dir 和 name 
//      System.out.println(dir+"---"+name);
        /*
         * 这里的儿子名字name都是String类型,而我们又想获取name的后缀名是.jpg
         * 所以也就是说我们需要判断字符串name的后面是否是.jpg,
         * 如果是就返回true,存储到数组中,否则不存储
         */
        //判断name的后缀名是否是.jpg
        boolean boo = name.endsWith(".jpg");
        /*
         * 还得判断儿子是否是文件 但是这里的name是字符串不能调用isFile()函数
         * 所以只能将儿子的名字name封装成File类的对象
         */
        File file = new File(dir,name);
        //判断儿子是否是文件 true 是文件 false不是文件
        boolean boo2 = file.isFile();
        return boo && boo2;
    }
}

使用public File[] listFiles(FilenameFilter filter) 函数方式来实现过滤功能。
测试类代码如下:

//public File[] listFiles(FilenameFilter filter) 返回符合过滤器中条件的儿子的File对象数组
        public static void method_2() {
            // 创建File类的对象
            File file = new File("D:\\test");
            /*
             * 使用file对象调用list(FilenameFilter filter) 函数来筛选D:\\test
             * 目录下儿子文件后缀名是.jpg
             */
            //获得符合条件的儿子的名字的数组
            File[] files = file.listFiles(new MyFilenameFilter());
            //遍历数组
            for (File file2 : files) {
                /*
                 * 这里的file2就是表示D:\\test目录下符合条件的儿子的对象
                 * 也就是说file2在这里就是所有后缀名为.jpg的文件的对象
                 * 如D:\\test目录下的1.jpg文件
                 * 由于题目需求是想获得儿子文件的绝对路径
                 * 想获得绝对路径必须得调用File类中的getAbsolutePath()函数
                 * 而这个函数是非静态函数得通过File的对象调用
                 * 所以这里直接使用file2调用即可
                 */
                System.out.println(file2.getAbsolutePath());
            }
        }
}

过滤器源码实现来说明FilenameFilter过滤器中accept()函数执行的时间:


23.png

说明:FilenameFilter:过滤器仅仅只能根据accept方法中name中包括的字符内容过滤当前的文件或文件夹。而不能直接去判断当前以name表示的那个字符串到底是文件还是文件夹,只能间接的重新封装name对象,然后根据封装后的对象调用isFile()函数判断是否是文件,虽然这样可以解决问题,但是不建议开发中使用上述这种方式。
Java中又给我们提供了一个比较简单的实现方式就是过滤器FileFilter。

3.3、FileFileter介绍

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


24.png

File类中的函数:
File[] listFiles(FileFilter filter) 返回符合过滤器条件的所有儿子的File数组
FileFilter过滤器中的accept方法中的pathname是当前需要过滤的那个文件或文件夹对象。
或者可以这么理解pathname:就是某个儿子的File对象。
这里的File pathname参数相当于:FilenameFilter过滤器中的自定义过滤器类MyFilenameFilter里面的代码:

File file=new File(dir,name);

需求:判断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.xuexi.file.filter.demo;
import java.io.File;
/*
 * 演示文件过滤器 FileFilter
 * 需求:判断D:\\test下是否有.jpg文件,如果有,则打印其绝对路径。
 */
public class FileFilterDemo {
    public static void main(String[] args) {
        // 创建父目录D:\\test的对象
        File file = new File("D:\\test");
        /*
         * 使用父目录对象file调用listFiles(FileFilter filter) 
         * 获得符合过滤器条件的儿子对象
         */
        File[] files = file.listFiles(new MyFileFilter());
        //遍历儿子对象的数组 file2表示符合条件的儿子对象
        for (File file2 : files) {
            //输出绝对路径
            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.xuexi.file.filter.demo;
import java.io.File;
import java.io.FileFilter;
/*
 * 自定义文件过滤器
 */
public class MyFileFilter implements FileFilter {
    public boolean accept(File pathname) {
        /*
         * 这里的pathname表示儿子的File类的对象
         * 这里的pathname就相当于FilenameFilter过滤器中的
         * new File(dir,name);
         */
//      System.out.println("======="+pathname);
        /*
         * 儿子对象有了,我们可以调用函数判断儿子是否是文件
         */
        boolean boo = pathname.isFile();
        /*
         * 接下来我们要判断儿子属于文件,文件的后缀名是否是.jpg
         * 那么我们要获得儿子的名字 getName()函数可以实现
         */
        String name = pathname.getName();
        //判断字符串name的后缀名是否是.jpg
        boolean boo2 = name.endsWith(".jpg");
        return boo && boo2;
    }
}

升级一下需求:获取D:\test下的所有任意指定类型的文件,打印绝对路径

分析:
原来:我们把判断条件写死成".jpg",所以只能判断扫描.jpg文件。
现在:我们要判断任意类型的文件,那么就不能写死。用户让我们过滤什么,我们就过滤什么。
说明:对于这里的程序来说,用户就是使用过滤器的地方,就是创建过滤器类对象的地方。
那么,过滤的条件需要让用户传递给过滤器。
用户调用过滤器的时候,仅仅是创造了过滤器类的构造函数,所以,我们考虑用构造函数传递参数。
过滤器类的代码如下所示:

package cn.xuexi.file.filter.demo;
import java.io.File;
import java.io.FileFilter;
/*
 * 自定义文件过滤器
 */
public class MyFileFilter implements FileFilter {
    //定义一个成员变量 代表后缀名
    public String suffix;
    //定义构造函数 接收调用传递过来的文件后缀名
    public MyFileFilter(String suffix)
    {
        this.suffix=suffix;
    }
    public boolean accept(File pathname) {
        /*
         * 这里的pathname表示儿子的File类的对象
         * 这里的pathname就相当于FilenameFilter过滤器中的
         * new File(dir,name);
         */
//      System.out.println("======="+pathname);
        /*
         * 儿子对象有了,我们可以调用函数判断儿子是否是文件
         */
        boolean boo = pathname.isFile();
        /*
         * 接下来我们要判断儿子属于文件,文件的后缀名是否是.jpg
         * 那么我们要获得儿子的名字 getName()函数可以实现
         */
        String name = pathname.getName();
        //判断字符串name的后缀名是否是.jpg
//      boolean boo2 = name.endsWith(".jpg");
        //判断字符串name的后缀名是否是suffix 这里的suffix由调用者决定
        boolean boo2 = name.endsWith(suffix);
        return boo && boo2;
    }
}

测试类的代码如下所示:

package cn.xuexi.file.filter.demo;
import java.io.File;
/*
 * 演示文件过滤器 FileFilter
 * 需求:判断D:\\test下是否有.jpg文件,如果有,则打印其绝对路径。
 */
public class FileFilterDemo {
    public static void main(String[] args) {
        // 创建父目录D:\\test的对象
        File file = new File("D:\\test");
        /*
         * 使用父目录对象file调用listFiles(FileFilter filter) 
         * 获得符合过滤器条件的儿子对象
         * 想要的文件类型由调用者决定 .txt
         */
        File[] files = file.listFiles(new MyFileFilter(".txt"));
        //遍历儿子对象的数组 file2表示符合条件的儿子对象
        for (File file2 : files) {
            //输出绝对路径
            System.out.println(file2.getAbsolutePath());
        }
    }
}

上述两个过滤器类的图解说明如下所示:


25.png

推荐阅读更多精彩内容