zoukankan      html  css  js  c++  java
  • chapter20_File类、递归

    chapter20_File类、递归

    File类

    1.1 概述

    java.io.File 类是文件和目录路径名的抽象表示

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

    主要用于文件和目录的创建、查找和删除等操作。

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

    重点:记几个单词

    • file:文件
    • path:路径
    • separator:分隔器
    • directtory:文件夹/目录

    1.2 构造方法

    • public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
    • public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
    • public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。
    • 操作路径不能写死了 Windows 和Linux系统的分隔符不同
      windows: C:developaa.txt
      Linux: C:/develop/a/a.txt
      所以正确写法
      "C:"+File.separator+"develop"+File.separator+"a"+File.separator+"a.txt"
    • 示例代码
    public static void main(String[] args) {
            /*
                static String pathSeparator  与系统有关的路径分隔分,为了方便,他被表示为一个字符串
                static char pathSeparatorChar 与系统有关的路径分隔符
    
                static String separator 与系统有关的默认名称分隔符,为了方便,他被表示为一个字符串
                static char separatorChar 与系统有关的默认分隔符
    
                操作路径不能写死了  Windows 和Linux系统的分隔符不同
                windows: C:developaa.txt
                Linux: C:/develop/a/a.txt
                所以正确写法
                "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:正斜杠 /
    
    
        }
    
    public class Demo002File {
        public static void main(String[] args) {
            show01();
            show02("d:\","a.txt");
            // d:a.txt
            show03();
        }
        /**
            File(String pathname)  通过将给定的路径名称字符串转换为抽象路径类创建一个引得File实例
            参数:
                String pathname:字符串的路径名称
                路径可以是文件夹结尾,也可以是文件结尾
                路径可以是相对路路径,也可以是绝对路径
                路径可以存在,也可以不存在
                创建File对象,只是把字符串路径封装为File对象,不考虑路径的真假情况
    
         */
        public static void show01(){
            File f1 = new File("D:\develop\Projects\IdeaProjects\03_API\08_FileAndRecursion\a.txt");
            System.out.println(f1);
            // 重写了Object类的toString方法  D:developProjectsIdeaProjects3_API8_FileAndRecursiona.txt
    
            File f2 = new File("D:\develop\Projects\IdeaProjects\03_API\08_FileAndRecursion");
            System.out.println(f2);
            // D:developProjectsIdeaProjects3_API8_FileAndRecursion
            File f3 = new File("a.txt");
            System.out.println(f3);
            // a.txt
        }
        /**
            File(String parent,String child) 根据 parent 路径名字符串和 child 路径名创建一个新File实例
            参数:把路径分成了两部分
                string parent :父路径
                string child:子路径
            好处:
                父路径和子路径,可以单独写,使用起来非常灵活;父路径和子路径都可以变化
         */
        public static void show02(String parent,String child){
            File file = new File(parent, child);
            System.out.println(file);
            // d:a.txt
        }
        /**
            File(File parent,String child) 根据 parent 抽象路径名和 child 路径名字符串来创建一个新的File类
            参数:
                File parent:父路径
                String child:子路径
            好处:
                父路径和子路径,可以单独写,使用起来非常灵活;父路径和子路径都可以变化
                父路径是File类型,可以使用File的方法对路劲进行一些操作,再使用路径创建对象
         */
        public static void show03(){
            File parent = new File("C:\");
            File file = new File(parent,"hello.java");
            System.out.println(file);
            // C:hello.java
        }
    }
    

    小贴士:

    1. 一个File对象代表硬盘中实际存在的一个文件或者目录。
    2. 无论该路径下是否存在文件或者目录,都不影响File对象的创建。

    1.3 常用方法

    获取功能的方法

    • public String getAbsolutePath() :返回此File的绝对路径名字符串。

    • public String getPath() :将此File转换为路径名字符串。

    • public String getName() :返回由此File表示的文件或目录的名称。

    • public long length() :返回由此File表示的文件的长度。

      方法演示,代码如下:

      public class Demo03File {
          public static void main(String[] args) {
              sho01();
              show02();
              show03();
              show04();
          }
      
      
          /**
           * public String getAbsolutePath(): 返回此File的绝对路径名字符串
           * 获取的构造方法中传递路径
           * 无论路径是绝对的还是相对的,getAbsolutePath方法返回的都是绝对路径
           */
          private static void sho01() {
              File f1 = new File("D:\develop\Projects\IdeaProjects\03_API\a.txt");
              String absolutePath1 = f1.getAbsolutePath();
              System.out.println(absolutePath1);
              // D:developProjectsIdeaProjects3_APIa.txt
      
              File f2 = new File("a.txt");
              String absolutePath2 = f2.getAbsolutePath();
              System.out.println(absolutePath2);
              // D:developProjectsIdeaProjects3_APIa.txt
          }
      
          /**
           * Public String getPath():将此File转换为路径名字符串
           * 获取的构造方法中传递的路径
           * <p>
           * toString方法调用的就是getPath方法
           * 源码:
           * public String toString(){
           * <p>
           * }
           */
          private static void show02() {
              File f1 = new File("D:\develop\Projects\IdeaProjects\03_API\a.txt");
              File f2 = new File("a.txt");
              String path1 = f1.getPath();
              System.out.println(path1);
              // D:developProjectsIdeaProjects3_APIa.txt
              String path2 = f2.getPath();
              System.out.println(path2);
              // a.txt
      
              System.out.println(f1);
              // D:developProjectsIdeaProjects3_APIa.txt
              System.out.println(f1.toString());
              // D:developProjectsIdeaProjects3_APIa.txt
          }
      
          /**
              public String getName():返回由此File表示的文件或目录的名称
           获取的就是构造方法传递路径的结尾部分(文件/文件夹)
           */
          public static void show03(){
              File f1 = new File("D:\develop\Projects\IdeaProjects\03_API\a.txt");
              String name1 = f1.getName();
              System.out.println(name1);
              // a.txt
              File f2 = new File("D:\develop\Projects\IdeaProjects\03_API");
              System.out.println(f2.getName());
              // 03_API
          }
          /**
              public lang length(): 返回由此File表示的文件长度
           获取构造方法中指定文件的大小,以字节为单位
           注意:
              文件夹没有大小概念,所以不能获取
              如果获取的文件不存在 那么length返回0
           */
          public static  void show04(){
              File f1 = new File("D:\develop\Projects\IdeaProjects\03_API\a.txt");
              long length = f1.length();
              System.out.println(length);
              File f = new File("D:\develop\Projects\IdeaProjects\03_API\a.txt");
              System.out.println(f);
          }
      
      }
      
      

    API中说明:length(),表示文件的长度。但是File对象表示目录,则返回值未指定。

    绝对路径和相对路径

    • 绝对路径:从盘符开始的路径,这是一个完整的路径。
      • 如E:BinMPlayera.txt
    • 相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
      • 如果使用的是当前项目的根目录,路径可以简化书写
      • 如E:BinMPlayera.txt-->a.txt(可以省略项目的根目录)

    注意:

    1. 路径不区分大小写
    2. 路径中的文件名称分隔符Windows使用反斜杠,反斜杠是转义字符,两个反斜杠代表一个普通反斜杠
    public class FilePath {
        public static void main(String[] args) {
          	// D盘下的bbb.java文件
            File f = new File("D:\bbb.java");
            System.out.println(f.getAbsolutePath());
          	
    		// 项目下的bbb.java文件
            File f2 = new File("bbb.java");
            System.out.println(f2.getAbsolutePath());
        }
    }
    输出结果:
    D:bb.java
    D:idea_project_test4bb.java
    

    判断功能的方法

    • public boolean exists():此File表示文件或目录是否实际存在

    • public boolean isDirectory(): 此File表示的是否为目录

      • 用于判断构造方法中给定的路径是否已文件夹结尾
      • 是:true
      • 否:false
    • public boolean isFile(): 此file表示的是否为文件

      • 用于判断构造方法中给定的路径是否已文件结尾
      • 是:true
      • 否:false
    • 注意:

      电脑的硬盘中只有文件/文件夹,两个方法时互斥的

      这两个方法使用的前提,路径必须是存在的,否则都返回false

    方法演示,代码如下:

    public class FileIs {
        public static void main(String[] args) {
            File f = new File("d:\aaa\bbb.java");
            File f2 = new File("d:\aaa");
          	// 判断是否存在
            System.out.println("d:\aaa\bbb.java 是否存在:"+f.exists());
            System.out.println("d:\aaa 是否存在:"+f2.exists());
          	// 判断是文件还是目录
            System.out.println("d:\aaa 文件?:"+f2.isFile());
            System.out.println("d:\aaa 目录?:"+f2.isDirectory());
        }
    }
    输出结果:
    d:aaabb.java 是否存在:true
    d:aaa 是否存在:true
    d:aaa 文件?:false
    d:aaa 目录?:true
    

    创建删除功能的方法

    • public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。

      • public boolean createNewFile() throws IOException

        createNewFile() 声明抛出异常 IOException,我们调用这个方法就必须处理这个异常,要么throws,要么try cath

    • public boolean delete() :删除由此File表示的文件或目录。

      • 文件夹中有内容不会删除
      • delete() 方法是直接在硬盘上删除文件/文件夹,不走回收站,删除要谨慎
    • public boolean mkdir() :创建由此File表示的目录。

    • public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。

    方法演示,代码如下:

    public class FileCreateDelete {
        public static void main(String[] args) throws IOException {
            // 文件的创建
            File f = new File("aaa.txt");
            System.out.println("是否存在:"+f.exists()); // false
            System.out.println("是否创建:"+f.createNewFile()); // true
            System.out.println("是否存在:"+f.exists()); // true
    		
         	// 目录的创建
          	File f2= new File("newDir");	
            System.out.println("是否存在:"+f2.exists());// false
            System.out.println("是否创建:"+f2.mkdir());	// true
            System.out.println("是否存在:"+f2.exists());// true
    
    		// 创建多级目录
          	File f3= new File("newDira\newDirb");
            System.out.println(f3.mkdir());// false
            File f4= new File("newDira\newDirb");
            System.out.println(f4.mkdirs());// true
          
          	// 文件的删除
           	System.out.println(f.delete());// true
          
          	// 目录的删除
            System.out.println(f2.delete());// true
            System.out.println(f4.delete());// false
        }
    }
    

    API中说明:delete方法,如果此File表示目录,则目录必须为空才能删除。

    1.4 目录的遍历

    • public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。

    • public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。

    public class FileFor {
        public static void main(String[] args) {
            File dir = new File("d:\java_code");
          
          	//获取当前目录下的文件以及文件夹的名称。
    		String[] names = dir.list();
    		for(String name : names){
    			System.out.println(name);
    		}
            //获取当前目录下的文件以及文件夹对象,只要拿到了文件对象,那么就可以获取更多信息
            File[] files = dir.listFiles();
            for (File file : files) {
                System.out.println(file);
            }
        }
    }
    

    小贴士:

    调用listFiles方法的File对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历。

    递归

    2.1 概述

    • 递归:指在当前方法内调用自己的这种现象。
    • 递归的分类:
      • 递归分为两种,直接递归和间接递归。
      • 直接递归称为方法自身调用自己。
      • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
    • 注意事项
      • 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
        • 当一个方法调用其他方法,被调用的方法没有执行完毕,当前方法就会一直等待调用的方法执行完毕,才会继续执行
      • 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
      • 构造方法,禁止递归
    public static void main(String[] args){
        a();
        b(1);
    }
    	/*
    	 * 1.递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。 Exception in thread "main"
    	 * java.lang.StackOverflowError
    	 */
    public static void a(){
        System.out.println("a方法");
    	a();
    }
    	/*
    	 * 2.在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
    	 * 4993
    	 * 	Exception in thread "main" java.lang.StackOverflowError
    	 */
    	private static void b(int i) {
    		System.out.println(i);
    		//添加一个递归结束的条件,i==5000的时候结束
    		if(i==5000){
    			return;//结束方法
    		}
    		b(++i);
    }
    /*
    	 * 3.构造方法,禁止递归
    	 * 编译报错:构造方法是创建对象使用的,不能让对象一直创建下去
    	 */
    	public Demo01DiGui() {
    		//Demo01DiGui();
    	}
    
    

    2.2 递归累加求和

    计算1 ~ n的和

    分析:num的累和 = num + (num-1)的累和,所以可以把累和的操作定义成一个方法,递归调用。

    已知:

    ​ 最大值:n

    ​ 最小值:1

    使用递归必须明确:

    ​ 1.递归结束的条件(获取到1的时候结束)

    ​ 2.递归的目的(获取到下一个被加的数字求和)

    实现代码

    public static void main(String[] args){
        int n = sum(3);
        System.out.println(n);
    }
    public static int sum(int n){
        // 获取到1的时候结束
        if(n==1){
            return 1;
        }
        // 获取下一个被加的数字(n-1)
        return n+sum(n-1);
    }
    

    代码执行图解

    小贴士:递归一定要有条件限定,保证递归能够停止下来,次数不要太多,否则会发生栈内存溢出。

    2.3 递归求阶乘

    • 阶乘:所有小于及等于该数的正整数的积。
    n的阶乘:n! = n * (n-1) *...* 3 * 2 * 1 
    

    分析:这与累和类似,只不过换成了乘法运算,学员可以自己练习,需要注意阶乘值符合int类型的范围。

    推理得出:n! = n * (n-1)!
    

    代码实现

    public class DiGuiDemo {
      	//计算n的阶乘,使用递归完成
        public static void main(String[] args) {
            int n = 3;
          	// 调用求阶乘的方法
            int value = getValue(n);
          	// 输出结果
            System.out.println("阶乘为:"+ value);
        }
    	/*
      	  通过递归算法实现.
      	  参数列表:int 
      	  返回值类型: int 
      	*/
        public static int getValue(int n) {
          	// 1的阶乘为1
            if (n == 1) {
                return 1;
            }
          	/*
          	  n不为1时,方法返回 n! = n*(n-1)!
              递归调用getValue方法
          	*/
            return n * getValue(n - 1);
        }
    }
    

    2.4 递归打印多级目录

    分析:多级目录的打印,就是当目录的嵌套。遍历之前,无从知道到底有多少级目录,所以我们还是要使用递归实现。

    代码实现

    public class Demo04Recurison {
        public static void main(String[] args) {
            File file = new File("D:\develop\Projects\IdeaProjects\03_API");
            getAllFile(file);
        }
        public static void getAllFile(File dir){
            System.out.println(dir);
            // 打印被遍历的目录名称
            File[] files = dir.listFiles();
            for (File f : files) {
                // 对遍历的得到的File对象f进行判断,是否是文件夹
                if (f.isDirectory()){
                    // f是一个文件夹,则继续遍历这个文件夹
                    // 方法getAllFile就是传递文件夹,遍历文件夹的方法
                    // 所以直接调用就可,递归(自己调用自己)
                    getAllFile(f);
                }else {
                    System.out.println(f);
                    // f是文件,直接打印
                }
            }
        }
    }
    
    

    第三章 综合案例

    3.1 文件搜索

    搜索D:aaa 目录中的.java 文件。

    分析

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

    ****代码实现**:

    public class DiGuiDemo3 {
        public static void main(String[] args) {
            // 创建File对象
            File dir  = new File("D:\aaa");
          	// 调用打印目录方法
            printDir(dir);
        }
    
        public static void printDir(File dir) {
          	// 获取子文件和目录
            File[] files = dir.listFiles();
          	
          	// 循环打印
            for (File file : files) {
                if (file.isFile()) {
                  	// 是文件,判断文件名并输出文件绝对路径
                    if (file.getName().endsWith(".java")) {
                        System.out.println("文件名:" + file.getAbsolutePath());
                    }
                } else {
                    // 是目录,继续遍历,形成递归
                    printDir(file);
                }
            }
        }
    }
    

    3.2 文件过滤器优化

    java.io.FileFilter是一个接口,是File的过滤器。 该接口的对象可以传递给File类的listFiles(FileFilter) 作为参数, 接口中只有一个方法。

    boolean accept(File pathname) :测试pathname是否应该包含在当前File目录中,符合则返回true。

    分析

    1. 接口作为参数,需要传递子类对象,重写其中方法。我们选择匿名内部类方式,比较简单。
    2. accept方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回false。保留规则:
      1. 要么是.java文件。
      2. 要么是目录,用于继续遍历。
    3. 通过过滤器的作用,listFiles(FileFilter)返回的数组元素中,子文件对象都是符合条件的,可以直接打印。

    代码实现:

    public class DiGuiDemo4 {
        public static void main(String[] args) {
            File dir = new File("D:\aaa");
            printDir2(dir);
        }
      
        public static void printDir2(File dir) {
          	// 匿名内部类方式,创建过滤器子类对象
            File[] files = dir.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith(".java")||pathname.isDirectory();
                }
            });
          	// 循环打印
            for (File file : files) {
                if (file.isFile()) {
                    System.out.println("文件名:" + file.getAbsolutePath());
                } else {
                    printDir2(file);
                }
            }
        }
    }      
    

    3.3 Lambda优化

    分析:FileFilter是只有一个方法的接口,因此可以用lambda表达式简写。

    lambda格式:

    ()->{ }
    

    代码实现:

    public static void printDir3(File dir) {
      	// lambda的改写
        File[] files = dir.listFiles(f ->{ 
          	return f.getName().endsWith(".java") || f.isDirectory(); 
        });
      	
    	// 循环打印
        for (File file : files) {
            if (file.isFile()) {
                System.out.println("文件名:" + file.getAbsolutePath());
          	} else {
            	printDir3(file);
          	}
        }
    }
    
  • 相关阅读:
    最大子数组求和并进行条件组合覆盖测试
    Ubuntu 16.04 c++ Google框架单元测试
    The directory '/home/stone/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If execu
    Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi'
    个人博客作业三:微软小娜APP的案例分析
    补交 作业一
    补交 作业二:个人博客作业内容:需求分析
    嵌入式软件设计第12次实验报告
    嵌入式软件设计第11次实验报告
    嵌入式软件设计第10次实验报告
  • 原文地址:https://www.cnblogs.com/anke-z/p/12653514.html
Copyright © 2011-2022 走看看