天天看点

【File类、递归】【File类、递归】

【File类、递归】

File类

java.io.File

类是文件和目录路径名的抽象表示形式。

Java吧电脑中的文件和文件夹(目录)封装为一个File类,我们可以使用File类对文件和文件夹进行操作。

我们可以使用File类的方法:

  • 创建一个文件/文件夹
  • 删除文件/文件夹
  • 获取文件/文件夹
  • 判断文件/文件夹是否存在
  • 对文件夹进行遍历
  • 获取文件的大小

File类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法。

重点,记住三个单词:file(文件)、directory(文件夹)、path(路径)。

成员变量

成员变量 含义
static String pathSeparator 与系统有关的路径分隔符,为了方便,它被表示为一个字符串
static char pathSeparatorChar 与系统有关的路径分隔符
static String Separator 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串
static char SeparatorChar 与系统有关的默认名称分隔符
import java.io.File;

public class Demo01File {
    public static void main(String[] args) {
        String pathSeparator = File.pathSeparator;
        System.out.println(pathSeparator);//路径分隔符,windows为:分号(;),Linux为冒号(:)。
        String separator = File.separator;
        System.out.println(separator);//文件名称分隔符,windows为:反斜杠(\),Linux为正斜杠(/)。
        /*因不同操作系统的文件名称分隔符不同
        写代码时,为保证可以多平台使用,路径不能写死
        c:\develop\a\a.txt   windows
        c:/develop/a/a.txt   linux
        改写为:
        “c:“+File.separator+”develop"+File.separator+"a"+File.separator+"a.txt”
        */
    }
}
           

绝对路径和相对路径

绝对路径:是一个完整的路径,是以盘符(c:、D:)开始的路径。

c:\a.txt

D:\Users\itcast\IdeaProjects\123.txt

C:\demo\B.txt

相对路径:是一个简化的路径,相对指的是相对于当前项目的根目录(C:\Users\Ann\Desktop\javaLearning)

如果使用当前项目的根目录,路径可以简化书写:

C:\Users\Ann\Desktop\javaLearning\HelloWorld.class -->简化为:HelloWorld.class

注意:

  1. 路径是不区分大小写的;
  2. 路径中的文件名称分隔符windows中使用反斜杠,反斜杠是转义字符,所以在书写中需要写两个反斜杠代表一个普通的反斜杠。

构造方法

  • File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新的File实例(对象)。
    • 参数:String pathname:字符串的路径名称
    • 路径可以以文件结尾,也可以以文件夹结尾
    • 路径可以是相对路径,也可以是绝对路径
    • 路径可以说存在的,也可以是不存在的
    • 创建File对象,只是把字符串路径封装为File对象,不考虑路径的真假情况
  • File(String parent,String child) 根据 parent 路径名字符串和 child 路径名字符串创建一个新File实例(对象)。
    • 参数:把路径分为了两部分:
      • String parent:父路径
      • String child:子路径
    • 好处:父路径和子路径可以单独书写,使用起来非常灵活;父路径和子路径都可以变化
  • File(File parent,String child) 根据 parent 抽象路径名和 child 路径名字符串创建一个新File实例(对象)。
    • 参数:把路径分为了两部分:
      • File parent:父路径
      • String child:子路径
    • 好处:
        1. 父路径和子路径可以单独书写,使用起来非常灵活;父路径和子路径都可以变化;
        2. 父路径是File类型,可以使用File的方法对路径进行一些操作,再使用路径创建对象。
import java.io.File;

public class Demo01FileConstructor {
    public static void main(String[] args) {
        File f1 = new File("c:"+File.separator+"develop"+File.separator+"a"+File.separator+"a.txt");
        System.out.println(f1);//重写了toString方法,c:\develop\a\a.txt
        File f2 = new File("c:"+File.separator,"a.txt");
        System.out.println(f2);//c:\a.txt
        File file = new File("c:"+File.separator);
        File f3 = new File(file,"a.txt");
        System.out.println(f3);//c:\a.txt

    }
}
           

常用的成员方法

获取功能的方法

方法 含义

public String getAbsolutePath()

返回此File的绝对路径字符串

public String getPath()

将此File转换为路径名字符串

toString方法内部就是调用此方法

public String getName()

返回由此File表示的文件或目录的名称

获取的就是构造方法传递路径的结尾部分(文件/文件夹)

public long length()

返回由此File表示的文件的长度

获取的是构造方法指定的文件的大小,以字节为单位

注意(对于length方法):

  1. 文件夹是没有大小概念的,不能获取文件夹的大小;
  2. 如果构造方法中给出的路径不存在,那么length方法返回0。

方法的代码演示,代码如下:

import java.io.File;

public interface Demo01FileGet {
    public static void main(String[] args) {
        File f1 = new File("c:\\ann\\a.txt");
        File f2 = new File("a.txt");

        System.out.println("文件的绝对路径为:" + f1.getAbsolutePath());
        //文件的绝对路径为:c:\ann\a.txt
        System.out.println("文件的绝对路径为:" + f2.getAbsolutePath());
        //文件的绝对路径为:C:\Users\Ann\Desktop\javaLearning\java\day18\a.txt

        System.out.println("文件的路径:" + f1.getPath());
        //文件的路径:c:\ann\a.txt
        System.out.println("文件的路径:" + f2.getPath());
        //文件的路径:a.txt

        File f3 = new File("C:\\Users\\Ann\\Desktop\\javaLearning\\java\\day18");

        System.out.println("路径的结尾:" + f1.getName());
        //路径的结尾:a.txt
        System.out.println("路径的结尾:" + f3.getName());
        //路径的结尾:day18

        File f4 = new File(f3, "day18.iml");
        System.out.println("不存在的文件的字节数:" + f1.length());
        //不存在的文件的字节数:0
        System.out.println("存在的文件的字节数:" + f4.length());
        //存在的文件的字节数:433
    }
}
           

判断功能的方法

方法 含义

public boolean exists()

此File表示的文件或目录是否实际存在

public boolean isDirectory()

此File表示的是否为目录

public boolean isFile()

此File表示的是否为文件
注意,对于isFile和isDirectory方法而言:
  1. 电脑的硬盘中只有文件/文件夹,这两个方法是互斥的;
  2. 这两个方法的使用前提,路径必须是存在的,否则返回false。

方法的代码演示,代码如下:

import java.io.File;

public class Demo01FileJudge {
    public static void main(String[] args) {
        File f1 = new File("c:\\","a.txt");
        File f2 = new File("C:"+File.separator+"Users"+File.separator+"Ann"+File.separator+"Desktop");
        File f3 = new File("day18.iml");
        //判断文件(目录)是否存在:
        System.out.println("文件1是否存在:"+f1.exists());//文件1是否存在:false
        System.out.println("文件2是否存在:"+f2.exists());//文件2是否存在:true
        System.out.println("文件3是否存在:"+f3.exists());//文件3是否存在:true

        fileJudge(f1);//c:\a.txt不存在
        fileJudge(f2);//Desktop为目录
        fileJudge(f3);//day18.iml为文件
    }
    //判断是否为文件/目录
    public static void fileJudge(File file){
        if(file.exists()){
            if (file.isFile()){
                System.out.println(file.getName()+"为文件");
            }else{
                System.out.println(file.getName()+"为目录");
            }
        }else{
            System.out.println(file.getAbsolutePath()+"不存在");
        }
    }
}
           

创建/删除功能的方法

方法 含义

public boolean createNewFile()

当且仅当具有该名称的文件尚不存在时,创建一个新的空文件

public boolean delete()

删除由此File表示的文件或目录

public boolean mkdir()

创建由此File表示的目录,只能创建单级文件夹

public boolean mkdirs()

创建由此File表示的目录,包括任何必需但不存在的父目录

既可以创建单级文件夹,也可以创建多级文件夹

注意:

  1. createNewFile方法只能创建文件,不能创建文件夹;
  2. createNewFile方法创建文件的路径必须存在,否则会抛出异常;
  3. mkdir/mkdirs方法只能创建文件夹,不能创建文件;
  4. delete方法是直接在硬盘中删除文件/文件夹的,不走回收站,删除要谨慎;
  5. delete方法删除只能删除单级文件夹,不能删除多级文件夹。

方法的代码演示,代码如下:

import java.io.File;
import java.io.IOException;

public class Demo01CreateDeleteFile {
    public static void main(String[] args) throws IOException {
        //1.创建文件的方法
        File f1 = new File("a.txt");
        //创建相对路径的文件
        boolean b1 = f1.createNewFile();
        System.out.println(b1);//ture

        File f2 = new File("C:\\Users\\Ann\\Desktop\\javaLearning\\java\\day18\\b.txt");
        //创建绝对路径的文件
        boolean b2 = f2.createNewFile();
        System.out.println(b2);//ture

        //2.创建文件夹的方法
        File f3 = new File("James");
        //在当前路径中创建名为James的文件夹
        boolean b3 = f3.mkdir();
        System.out.println(b3);//true

        File f4 = new File("src");
        //在当前路径中创建src文件夹,该文件夹已存在,不再新建,返回false
        boolean b4 = f4.mkdir();
        System.out.println(b4);//false

        File f5 = new File("C:\\Users\\Desk\\java\\day18");
        //构造方法中给出的路径不存在,无法新建文件夹,返回false
        boolean b5 = f5.mkdir();
        System.out.println(b5);//false

        File f6 = new File("Kobe\\81points");
        //在当前路径中创建多级文件夹
        boolean b6 = f6.mkdirs();
        System.out.println(b6);//true

        //3.删除文件/文件夹的方法
        boolean b7 = f6.delete();
        System.out.println(b7);//true,删除了81points这个单级文件夹
    }
}
           

File类遍历目录(文件夹)功能

方法 含义

public String[] list()

返回一个String数组,表示该File目录中的所有子文件或目录

public File[] listFiles()

返回一个File数组,表示该File目录中的所有的子文件或目录

注意:

  1. list方法和listFiles方法遍历的是构造方法中给出的目录;
  2. 如果构造方法中给出的目录的路径不存在,就会抛出空指针异常;
  3. 如果构造方法中给出的路径不是一个目录,也会抛出空指针异常;
  4. list方法和listFiles方法可以获得隐藏的文件夹。

方法的代码演示,代码如下:

import java.io.File;
import java.util.Arrays;

public class Demo01GoThroughFile {
    public static void main(String[] args) {
        File f1 = new File("C:\\Users\\Ann\\Desktop\\javaLearning");
        String[] arr = f1.list();
        System.out.println(Arrays.toString(arr));
        //[HelloWorld.class, HelloWorld.java, java, JDK 11 API中文帮助文档.CHM, JDK 11 API中文帮助文档.chw, Windows工具, 笔记]

        File[] fileArray = f1.listFiles();
        //返回的是绝对路径
        System.out.println(Arrays.toString(fileArray));
        //[C:\Users\Ann\Desktop\javaLearning\HelloWorld.class, C:\Users\Ann\Desktop\javaLearning\HelloWorld.java, C:\Users\Ann\Desktop\javaLearning\java, C:\Users\Ann\Desktop\javaLearning\JDK 11 API中文帮助文档.CHM, C:\Users\Ann\Desktop\javaLearning\JDK 11 API中文帮助文档.chw, C:\Users\Ann\Desktop\javaLearning\Windows工具, C:\Users\Ann\Desktop\javaLearning\笔记]
    }
}
           

递归

  • **递归:**指在当前方法内调用自己的这种现象。
  • 递归的分类:
    • 递归分为两种,直接递归和间接递归。
    • 直接递归称为方法自身调用自己。
    • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
  • 注意事项:
    • 递归一定要条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
    • 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
    • 构造方法,禁止递归。
      • 编译报错:构造方法是创建对象使用的,一直递归会导致内存中有无数个对象。

递归求和练习

public class Recursion {
    public static void main(String[] args) {
        int num = 9;
        int sum = getSum(num);
        System.out.println(sum);
    }

    public static int getSum(int num) {
        if (num == 1) {//递归的结束条件,n == 1
            return 1;
        }
        return getSum(num - 1) + num;//递归的目的:获取下一个被加的数字n-1

    }
}
           

###递归计算阶乘

public class Recursion {
    public static void main(String[] args) {
        int num = 3;
        int accumulation = factorial(num);
        System.out.println(accumulation);
    }

    public static int factorial(int num) {
        if (num == 1) {
            return 1;
        }
        return factorial(num - 1) * num;

    }
}
           

递归打印多级文件夹

import java.io.File;

public class Demo02Recursion {
    public static void main(String[] args) {
        File f1 = new File("C:\\Users\\Ann\\Desktop\\javaLearning\\java\\day18");
        getAllFile(f1);

    }

    public static void getAllFile(File dir) {
        System.out.println(dir);
        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                getAllFile(file);
            } else {
                System.out.println(file.getAbsolutePath());
            }
        }
    }
}
           

综合案例

文件搜索

搜索

"C:\\Users\\Ann\\Desktop\\javaLearning\\java\\day18"

目录下的

.java

文件

分析:

  1. 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录;
  2. 遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。

代码实现:

import java.io.File;

public class Demo02Recursion {
    public static void main(String[] args) {
        File f1 = new File("C:\\Users\\Ann\\Desktop\\javaLearning\\java\\day18");
        getAllFile(f1);

    }

    public static void getAllFile(File dir) {
        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                getAllFile(file);
            } else{
                if (file.getName().contains(".java")){
                    System.out.println(file.getAbsolutePath());
                }
            }
        }
    }
}
           

文件过滤器优化

我们可以使用过滤器来实现。

在File类中有两个listFiles重载的方法,方法的参数传递的就是过滤器。

  • File[] listFiles(FileFilter filter)

    • java.io.FileFilter

      接口:实现此接口的类实例是用于过滤抽象路径名(File对象)的过滤器。
      • 作用:用来过滤文件(File对象)
      • 抽象方法:用来过滤文件的方法
        • boolean accept(File pathname)

          :测试指定抽象路径名是否应该包含在某个路径名列表中。
  • File[] listFiles(FilenameFilter filter)

    • java.io.FilenameFilter

      接口:实现此接口的类实例是用于过滤文件名的过滤器。
      • 作用:用于过滤文件名称
      • 抽象方法:用来过滤文件的方法
        • boolean accept(File dir,String name)

          :测试指定文件是否应该包含在某一文件列表中。
注意:两个实现类没有现存的实现类,需要我们自己写实现类,重写过滤的方法accept,在方法中自己定义过滤的规则。

对于

listFiles(FileFilter filter)

方法中,需要明确的两个问题是:

  1. 过滤器中的accept方法是被谁调用的?
  2. accept方法的参数pathname是什么?

listFiles(FileFilter filter)

方法一共做了三件事情:

  1. listFiles

    方法会将构造方法中传递得到目录进行遍历,获取目录中的每一个文件/文件夹–>封装为File对象;
  2. listFiles

    方法会调用参数传递的过滤器对象中的accept方法;
  3. listFiles

    方法会将遍历得到的每一个对象传递给accept方法作为其参数pathname。

因此,对于上面的文件搜索的代码,可进行以下优化:

public class Demo02Recursion {
    public static void main(String[] args) {
        File f1 = new File("C:\\Users\\Ann\\Desktop\\javaLearning\\java\\day18");
        getAllFile(f1);
    }
    public static void getAllFile(File dir) {
        File[] files = dir.listFiles((pathname) -> pathname.isDirectory()||pathname.getName().contains(".java"));;
        for (File file : files) {
            if (file.isDirectory()) {
                getAllFile(file);
            } else {
                System.out.println(file.getAbsolutePath());
            }
        }
    }
}
           

而对于

listFiles(FilenameFilter filter)

方法,可写为:

public class Demo02Recursion {
    public static void main(String[] args) {
        File f1 = new File("C:\\Users\\Ann\\Desktop\\javaLearning\\java\\day18");
        getAllFile(f1);
    }

    public static void getAllFile(File dir) {
        File[] files = dir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return new File(dir,name).isDirectory()||name.toLowerCase().contains(".java");
            }
        });
        for (File file : files) {
            if (file.isDirectory()) {
                getAllFile(file);
            } else {
                System.out.println(file.getAbsolutePath());
            }
        }
    }
}