File类、递归

一、File类

1、概述

  • java.io.File类:是文件和目录(文件夹)路径名的抽象表示,主要用于文件和目录的创建、删除和查找等操作。

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

记住三个单词:

​ file:文件 directory:文件夹/目录 path:路径

2、Field

File类的静态成员变量:

  • public static final String pathSeparator 与系统有关的路径分隔符;为了方便,它被表示为一个字符串
  • public static final char pathSeparatorChar 与系统有关的路径分隔符

注意:两者是一样的

​ public static final String pathSeparator = "" + pathSeparatorChar;

  • public static final String separator 与系统有关的默认名称分隔符;为了方便,它被表示为一个字符串
  • public static final char separatorChar 与系统有关的默认名称分隔符

注意:两者是一样的

​ public static final String separator = "" + separatorChar;

import java.io.File;
public class Demo1File{
    public static void main(String[] args){
        /*
        	注意:操作路径时,路径不能写死。(因为各个OS所使用的分隔符不同)
        		C:\develop\a\a.txt  windows
                C:/develop/a/a.txt  linux
            "C:"+File.separator+"develop"+File.separator+"a"+File.separator+"a.txt"
        */
        String pathSeparator = File.pathSeparator;
        System.out.println(pathSeparator); //; 路径分隔符。windows:分号;  linux:冒号:
        String separator = File.separator;
        System.out.println(separator); //\ 文件名称分隔符。windows:反斜杠\  linux:正斜杠/
        
    }
}

3、路径

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

​ C:\Users\Administrator\Desktop\Markdown study

​ D:\Course\JavaSE\基础语法\src\day08\file\demo1\File

相对路径:是一个简化的路径

​ 相对指的是相对于当前项目的根目录;如果使用当前项目的根目录,路径可以简化书写。

​ D:\Course\JavaSE\基础语法\src\a.txt --> 简化为 a.txt(可以省略项目的根目录)

注意:

  • 路径不区分大小写
  • 路径中的文件名称分隔符windows使用反斜杠,而在java中反斜杠是转义字符,两个反斜杠才代表一个普通的反斜杠。

4、Constructor

  • public File(String pathname); 通过将给定的路径名字符串转换为抽象路径名来创建一个新File实例
import java.io.File;
public class Demo2File{
    public static void main(String[] args){
  /*
 	public File(String pathname); 通过将给定的路径名字符串转换为抽象路径名来创建一个新File实例
    	参数:
        	String pathname:路径名字符串
            路径可以是以文件结尾,也可以是以文件夹结尾
            路径可以是相对路径,也可以是绝对路径
            路径可以是存在,也可以是不存在
    	创建File对象,只是把字符串路径封装为File对象,不考虑路径的真假情况
  */
        //绝对路径 以文件结尾 且不存在
        File f1 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study\\a.txt");
        //C:\Users\Administrator\Desktop\Markdown study\a.txt
        System.out.println(f1); //重写了Object类的toString() 

        //绝对路径 以文件夹结尾 存在
        File f2 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study");
        System.out.println(f2); //C:\Users\Administrator\Desktop\Markdown study

        //相对路径
        File f3 = new File("b.txt");
        System.out.println(f3); //b.txt
    }
}
  • public File(String parent,String child); 根据父路径字符串和子路径字符串创建一个新File实例
import java.io.File;
public class Demo3File{
    public static void main(String[] args){
    /*
    	public File(String parent,String child); 根据父路径字符串和子路径字符串创建一个新File实例
        参数:把路径分成了两部分
            String parent:父路径
            String child:子路径
        好处:
            父路径和子路径可以单独书写,使用起来非常灵活;父路径和子路径都可以变化。
    */
        show02("c:\\","a.txt"); //c:\a.txt
        show02("d:\\","a.txt"); //d:\a.txt
    }
    
    public static void show02(String parent,String child) {
   		 File file = new File(parent,child);
       	 System.out.println(file);
   }
}
  • public FIle(File parent,String child); 根据 parent 抽象路径名和 child 路径名字符串创建一个新File实例
import java.io.File;
public class Demo4File{
    public static void main(String[] args){
    /*
    public File(File parent,String child); 根据父抽象路径名和子路径名字符串创建一个新File实例
    参数:把路径分成了两部分
        String parent:父路径
        String child:子路径
    好处:
        父路径和子路径可以单独书写,使用起来非常灵活;父路径和子路径都可以变化。
        父路径是File类型,可以使用File的方法对路径进行一些操作,再使用路径创建对象。
    */
        show03();
    }
    
    public static void show03(){
        File parent = new File("d:\\");
        File file = new File(parent,"hello.java");
        System.out.println(file); //d:\hello.java
    }
}

5、常用方法

5.1 获取功能的方法

  • public String getAbsolutePath(); 返回此File的绝对路径名字符串
import java.io.File;
public class Demo5File{
    public static void main(String[] args){
    /*
    	public String getAbsolutePath(); 返回此File的绝对路径名字符串
            获取的构造方法中传递的路径
            无论路径是绝对的还是相对的,getAbsolutePath方法返回的都是绝对路径
    */
        File f1 = new File("D:\\Course\\JavaSE\\基础语法\\src\\Day08\\a.txt");
        String absolutePath1 = f1.getAbsolutePath();
        System.out.println(absolutePath1); //D:\Course\JavaSE\基础语法\src\Day08\a.txt

        File f2 = new File("a.txt");
        String absolutePath2 = f2.getAbsolutePath();
        System.out.println(absolutePath2); //D:\Course\JavaSE\基础语法\src\a.txt
    }
}
  • public String getPath(); 将此File转换为路径名字符串
import java.io.File;
public class Demo6File{
    public static void main(String[] args){
    /*
    	public String getPath();  将此File转换为路径名字符串
        	获取的构造方法中传递的路径
            传递的是绝对路径就返回绝对路径,传递的相对路径就返回相对路径。

        File类中重写的toString()调用的就是getPath()。
        源码:
            public String toString() {
                return getPath();
            }
    */
        
        File f1 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study");
        File f2 = new File("b.txt");
        String path1 = f1.getPath();
        String path2 = f2.getPath();
        System.out.println(path1); //C:\Users\Administrator\Desktop\Markdown study
        System.out.println(path2); //b.txt

        System.out.println(f1); //C:\Users\Administrator\Desktop\Markdown study
        System.out.println(f1.toString()); //C:\Users\Administrator\Desktop\Markdown study

    }
}

  • public String getName(); 返回由此File表示的文件/目录的名称
import java.io.File;
public class Demo7File{
    public static void main(String[] args){
    /*
    	public String getName();  返回由此File表示的文件/目录的名称
            获取的就是构造方法传递路径的结尾部分(文件/文件夹)
    */
        
        File f1 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study\\a.txt");
        String name1 = f1.getName();
        System.out.println(name1); //a.txt 获取的结尾部分是文件

        File f2 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study");
        String name2 = f2.getName();
        System.out.println(name2); //Markdown study  获取的结尾部分是文件夹
        
    }
}
  • public long length(); 返回由此File表示的文件的大小
import java.io.File;
public class Demo8File{
    public static void main(String[] args){
  	/*
  		public long length();   返回由此File表示的文件的大小
            获取的是构造方法指定的文件的大小,以字节为单位。
        注意:
            1.文件夹是没有大小概念的,不能获取文件夹的大小
            2.如果构造方法中给出的路径不存在,那么length方法返回0
  	*/     
        
        File f1 = new File("C:\\Users\\Administrator\\Desktop\\a\\1.jpg");
        long l1 = f1.length();
        System.out.println(l1); //388260字节

        File f2 = new File("C:\\Users\\Administrator\\Desktop\\a\\2.jpg");
        System.out.println(f2.length()); //0

        File f3 = new File("C:\\Users\\Administrator\\Desktop\\a");
        System.out.println(f3.length()); //0 文件夹是没有大小概念的
        
    }
}

5.2 判断功能的方法

  • public boolean exists(); 判断此File表示的文件/目录是否实际存在
import java.io.File;
public class Demo9File{    
  public static void main(String[] args){    
  /*    	
    public boolean exists(); 判断此File表示的文件/目录是否实际存在            
    用于判断构造方法中的路径是否存在                
      存在:true                
      不存在:false    
  */                    
    File f1 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study");        
    System.out.println(f1.exists()); //true        
    File f2 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study\\a.txt");        
    System.out.println(f2.exists()); //false        
    File f3 = new File("day03");        
    System.out.println(f3.exists()); //true        
    File f4 = new File("dayday");        
    System.out.println(f4.exists()); //false            
  }
}
  • public boolean isDirectory(); 判断此File表示的是否为目录
  • public boolean isFile(); 判断此File表示的是否为文件
import java.io.File;
public class Demo10File{   
  public static void main(String[] args){    
  /*    	
    public boolean isDirectory(); 判断此File表示的是否为目录            
    用于判断构造方法中给定的路径是否以文件夹结尾                
      是:true                
      否:false        
    public boolean isFile(); 判断此File表示的是否为文件            
    用于判断构造方法中给定的路径是否以文件结尾                
      是:true                
      否:false        
    注意:            
      电脑的硬盘只有文件和文件夹,两个方法是互斥            
      这两个方法使用前提:路径必须是存在的,否则都返回false    
  */                 
    File f1 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study\\t.txt");        
    System.out.println(f1.isDirectory()); //false 文件不存在        
    System.out.println(f1.isFile()); //false  文件不存在        
    File f2 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study");        
    //加个判断,不存在就没有必要获取        
    if(f2.exists()){            
      System.out.println(f2.isDirectory()); //true 存在 以文件夹结尾            
      System.out.println(f2.isFile()); //false 存在 不是以文件结尾        
    }        
    File f3 = new File("C:\\Users\\Administrator\\Desktop\\Markdown study\\Day01.md");        
    if(f3.exists()){            
      System.out.println(f3.isDirectory()); //false 存在 不是以文件结尾            
      System.out.println(f3.isFile()); //true 存在 以文件结尾        
    }            
  }
}

5.3 创建、删除功能的方法

  • public boolean creatNewFile(); 当且仅当具有该名称的文件不存在时,创建一个新的文件
import java.io.File;
public class Demo11File{    
  public static void main(String[] args){    
  /*    	 
    public boolean createNewFile(); 当且仅当具有该名称的文件不存在时,创建一个新的文件            
    创建文件的路径和名称在构造方法中给出(构造方法的参数)        
    返回值:布尔值            
      true:文件不存在,创建文件,返回true            
      false:文件存在,不会创建,返回false        
    注意:            
      1.此方法只能创建文件,不能创建文件夹            
      2.创建文件的路径必须存在,否则会抛出异常。    
  */                
    //绝对路径:        
    File f1 = new File("C:\\Users\\Administrator\\Desktop\\a\\xzw.txt");        
    boolean b1 = f1.createNewFile();        
    System.out.println("b1: " + b1); //true        
    //相对路径:相对于当前项目所在的根目录        
    File f2 = new File("lyq.txt");        
    boolean b2 = f2.createNewFile();        
    System.out.println("b2: " + b2);        
    File f3 = new File("C:\\Desktop\\lss\\xzw\\lyq.txt");        
    boolean b3 = f3.createNewFile();        
    System.out.println(b3); //路径不存在 抛出IOException!            
  }
}
  • public boolean delete(); 删除由此File表示的文件或目录
  • public boolean mkdir(); 创建单级文件夹
  • public boolean mkdirs(); 既可以创建单级文件夹,也可以创建多级文件夹
/*        
public boolean mkdir(); 创建单级文件夹        
public boolean mkdirs(); 既可以创建单级文件夹,也可以创建多级文件夹            
创建文件的路径和名称在构造方法中给出(构造方法的参数)        
  返回值:布尔值            
    true:文件夹不存在,创建文件夹,返回true            
    false:文件夹存在,不会创建,返回false;构造方法中给出的文件夹路径不存在,也返回false        
  注意:            
    此方法只能创建文件夹,不能创建文件        

public boolean delete(); 删除由此File表示的文件或目录            
此方法,可以删除构造方法路径中给出的文件/文件夹        
  返回值:布尔值            
    true:文件/文件夹删除成功,返回true            
    false:文件夹中有内容,不会删除返回false;构造方法中路径不存在,也返回false        
  注意:            
    delete方法是直接在硬盘删除文件/文件夹,不走回收站,删除要谨慎!     
*/

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

  • public String[ ] list(); 返回一个String数组,表示该File目录中的所有子文件或目录
import java.io.File;
public class Demo12File{    
  public static void main(String[] args){    
    /*    	
      public String[] list(); 返回一个String数组,表示该File目录中的所有子文件或目录            
        遍历构造方法中给出的目录,会获取目录中所有文件/文件夹的名称,把获取到的多个名称            
        存储到一个String类型的数组中。        	
      能够获取到隐藏的文件/文件夹。    
    */            
    //NullPointerException  文件不存在        
    //File f1 = new File("D:\\Course\\JavaSE\\基础语法\\src\\Day0\\file");         
    //NullPointerException  给出的路径不是一个目录        
    //File f1 = new File("D:\\Course\\JavaSE\\基础语法\\src\\基础语法.iml");         
    File f1 = new File("D:\\Course\\JavaSE\\基础语法\\src\\Day08\\file");        
    String[] arr1 = f1.list();        
    for (String s : arr1) {            
      System.out.println(s);        
    }            
  }
}
  • public File[ ] listFiles(); 返回一个File数组,表示该File目录中的所有子文件或目录
import java.io.File;
public class Demo13File{    
  public static void main(String[] args){    
  /*    	
    public File[] listFiles();  返回一个File数组,表示该File目录中的所有子文件或目录            
    遍历构造方法中给出的目录,会获取目录中所有文件/文件夹的名称,把文件/文件夹封装为File对象,            
    将多个File对象存储到数组中。    
  */                
    File f1 = new File("D:\\Course\\JavaSE\\基础语法\\src\\Day08\\file");        
    File[] arr = f1.listFiles();        
    for(File f : arr){            
      System.out.println(f);        
    }            
  }
}
注意:
   list和listFiles方法遍历的是构造方法中给出的目录
   如果构造方法中给出的目录的路径不存在,会抛出空指针异常!
   如果构造方法给出的路径不是一个目录,也会抛出空指针异常!

二、递归

1、概述

  • 指在当前方法内调用自己的这种现象。(方法自己调用自己)

2、分类

  • 直接递归:方法自身调用自己。
  • 间接递归:A方法调用B方法,B方法调用C方法,C方法调用A方法。

注意事项:

​ a. 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。

​ b. 在递归中虽然有限定条件,但是递归次数不能太多,否则也会发生栈内存溢出。

​ c. 构造方法,禁止递归。

​ 构造方法是创建对象使用的,一直递归会导致内存中有无数多个对象,直接编译报错。

使用递归的前提:

​ 当调用方法的时候,方法的主体不变,每次调用方法的参数不同,可以使用递归。

3、案例分析

3.1 计算1~n的和

/*    
  利用递归:计算1~n的和。 (用for循环更好!) 
*/
public class Demo1Recursion {    
  public static void main(String[] args) {        
    System.out.println(sum(100));    
  }    

  public static int sum(int n){        
    if(n == 1){            
      return 1;        
    }        
    return n + sum(n-1);    
  }
}

3.2 计算n!

/*	
  利用递归:计算n的阶乘。
*/
public class Demo2Recursion {    
  public static void main(String[] args) {        
    int result = f(5);        
    System.out.println(result);    
  }    

  public static int f(int n){        
    if(n == 1){            
      return 1;        
    }        
    return n * f(n - 1);    
  }
}

3.3 用递归打印多级目录

import java.io.File;
/*    
  递归打印多级目录:        
  C:\Users\Administrator\Desktop\abc             
    a文件夹:                
      a.txt                
      1.jpg            
    b文件夹:                
      b.txt                
      2.jpg            
    lyq.java文件            
    xzw.txt文件 
*/
public class Demo3Recursion {    
  public static void main(String[] args) {        
    File file = new File("C:\\Users\\Administrator\\Desktop\\abc");        
    getAllFile(file);    
  }    
  //定义一个遍历文件夹的方法    
  public static void getAllFile(File dir) {        
    System.out.println(dir.getName()); //打印遍历的目录名称        
    File[] files = dir.listFiles();        
    for (File f : files) {            
    //对遍历的对象进行判断,判断是否为文件夹            
      if (f.isDirectory()) {                
        //f是一个文件夹,则继续遍历这个文件夹                
        //发现getAllFile方法就是传递文件夹,遍历文件夹的方法                
        //所以直接调用getAllFile方法即可:递归(自己调用自己)                
        getAllFile(f);            
      } else {                
        //是一个文件,直接打印即可                
        System.out.println(f);            
      }        
    }    
  }
}

3.4 用递归进行文件搜索

import java.io.File;
/*    
  文件搜索:搜索C:\Users\Administrator\Desktop\abc目录中以.java结尾的文件:    
  abc文件夹包含:        
    a文件夹:            
      a.txt            
      1.jpg        
    b文件夹:            
      b.txt            
      2.jpg        
    lyq.java文件        
    xzw.txt文件 
*/
public class Demo5Recursion {    
  public static void main(String[] args) {        
    File file = new File("C:\\Users\\Administrator\\Desktop\\abc");        
    getAllFile(file);    
  }    

  public static void getAllFile(File dir) {        
    File[] files = dir.listFiles();        
    for (File f : files) {            
      //对遍历的对象进行判断,判断是否为文件夹            
      if (f.isDirectory()) {                
        //f是一个文件夹,则继续遍历这个文件夹                
        //发现getAllFile方法就是传递文件夹,遍历文件夹的方法                
        //所以直接调用getAllFile方法即可:递归(自己调用自己)                
        getAllFile(f);            
      } else {                
          //是一个文件,直接打印即可                
        /*                    
            C:\Users\Administrator\Desktop\abc\lyq.java                    
              只要.java结尾的文件                    
              1.把File对象f,转为字符串对象                 
        */                
        /*                
          //String name = f.getName(); //lyq.java                
          //String path = f.getPath(); 	
          //C:\Users\Administrator\Desktop\abc\lyq.java                
          String s = f.toString(); //C:\Users\Administrator\Desktop\abc\lyq.java                
          //把字符串转换为小写                
          s = s.toLowerCase();                
          //2.调用String类中的方法endsWith判断字符串是否以.java结尾                
          boolean b = s.endsWith(".java");                
          //3.如果是以.java结尾的,则输出                
          if(b){                    
            System.out.println(f);                
          }                 
        */                
          //链式编程:简化代码                
          if(f.toString().toLowerCase().endsWith(".java")){                    
            System.out.println(f);                
          }            
        }        
      }    
    }
}

4、FileFilter文件过滤器

import java.io.File;
import java.io.FileFilter;
/*    
  需求:        
    遍历C:\Users\Administrator\Desktop\abc文件夹,及abc文件夹的子文件夹        
    只要以.java结尾的文件:    
  C:\Users\Administrator\Desktop\abc        
    C:\Users\Administrator\Desktop\abc\lyq.java        
    C:\Users\Administrator\Desktop\abc\xzw.txt        
    C:\Users\Administrator\Desktop\abc\a            
      C:\Users\Administrator\Desktop\abc\a\1.jpg            
      C:\Users\Administrator\Desktop\abc\a\a.JAVA        
    C:\Users\Administrator\Desktop\abc\b            
      C:\Users\Administrator\Desktop\abc\b\b.java            
      C:\Users\Administrator\Desktop\abc\b\b.txt    

  可以使用过滤器来实现:    
  在File类中有两个和listFiles重载的方法,方法的参数传递的就是过滤器: 
       
  File[] listFiles(FileFilter filter)        
  java.io.FileFilter接口:用于抽象路径名(File对象)的过滤器            
  作用:用来过滤文件(File对象)            
  包含抽象方法:用来过滤文件的方法                
    boolean accept(File pathname) 测试指定抽象路径名是否应该包含在某个路径名列表中                
    参数:                    
      File pathname:使用listFiles方法遍历目录,得到的每一个文件对象。    
     
  File[] listFiles(FilenameFilter filter)         
  java.io.FilenameFilter接口:实现此接口的类实例可用于过滤器文件名。            
  作用:用来过滤文件名称            
  包含抽象方法:用来过滤文件的方法                
    boolean accept(File dir,String name) 测定指定文件是否应该包含在某一文件列表中                
    参数:                    
      File dir:构造方法中传递的被遍历的目录                    
      String name:使用listFiles方法遍历目录,获取的每一个文件/文件夹的名称   
 
  注意:        
    两个过滤器接口是没有实现类的,需要我们自己写实现类,重写过滤的方法accept,在方法中定义过滤的规则。 
*/
public class Demo1Filter {    
  public static void main(String[] args) {        
    File file = new File("C:\\Users\\Administrator\\Desktop\\abc");        
    getAllFile(file);    
  }    

  //定义一个方法:参数传递File类型的目录,方法中对目录进行遍历    
  public static void getAllFile(File dir) {        
    File[] files = dir.listFiles(new FileFilterImpl(            
    /*   				 
      创建过滤器FileFilter的实现类(匿名内部类)   				 
      重写过滤方法accept,定义过滤规则。			 
    */            
      @Override            
      public boolean accept(File pathname) {                
      /*                    
        过滤的规则:                        
          在accept方法中,判断File对象是否以.java结尾                        
            如果是,返回true                        
            否则,返回false                 
      */                
      //如果pathname是一个文件夹,返回true,继续遍历这个文件夹                
      if(pathname.isDirectory()){                    
        return true;                
      }                
      return pathname.getName().toLowerCase().endsWith(".java");    		
    }));                 

    //传递过滤器对象        
    for (File f : files) {            
      //对遍历的对象进行判断,判断是否为文件夹            
      if (f.isDirectory()) {                
        //f是一个文件夹,则继续遍历这个文件夹                
        //发现getAllFile方法就是传递文件夹,遍历文件夹的方法                
        //所以直接调用getAllFile方法即可:递归(自己调用自己)                
        getAllFile(f);            
      } else {                
        //是一个文件,直接打印即可                
        System.out.println(f);            
      }        
    }    
  }
}

posted @ 2021-06-21 15:18  Sleepinglion  阅读(79)  评论(0)    收藏  举报