今日内容

  • File类------->重点掌握
    • 概述
    • 构造方法
    • 成员方法
  • 递归------->重点掌握
    • 如何递归(实现)
    • 分析递归程序的执行流程
  • IO流的概述和分类
    • 输入和输出的概念
    • IO流的分类
  • 字节流------->重点掌握
    • 字节输入流: 读数据
    • 字节输出流: 写数据
  • 字符流------->重点掌握
    • 字符输入流: 读数据
    • 字符输出流: 写数据

第一章 File类

1.1 File类的概述和构造方法

File类的概述

java.io.File 类是用来表示文件或者文件夹路径,可以用于对文件和文件夹的创建、查找和删除等操作。

File类的构造方法

  • public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。

  • public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。

  • public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。

  • 注意:

    • 创建File对象时,如果传入的文件或者文件夹路径不存在,依然不影响File对象的创建
  • 构造举例,代码如下:

    /**
     * Created by PengZhiLin on 2021/8/10 9:16
     */
    public class Test {
        public static void main(String[] args) {
            //- `public File(String pathname) ` :通过将给定的**路径名字符串**转换为抽象路径名来创建新的 File实例。
            File f1 = new File("G:\\szitheima119\\day10\\aaa\\a.txt");
            System.out.println("f1:" + f1);
    
            //- `public File(String parent, String child) ` :从**父路径名字符串和子路径名字符串**创建新的 File实例。
            File f2 = new File("G:\\szitheima119\\day10\\aaa", "a.txt");
            System.out.println("f2:" + f2);
    
            //- `public File(File parent, String child)` :从**父抽象路径名和子路径名字符串**创建新的 File实例。
            File parent = new File("G:\\szitheima119\\day10\\aaa");
            File f3 = new File(parent, "a.txt");
            System.out.println("f3:" + f3);
    
            // 注意:**创建File对象时,如果传入的文件或者文件夹路径不存在,依然不影响File对象的创建**
            File f4 = new File("G:\\szitheima119\\day10\\aaa\\b.txt");
            System.out.println("f4:" + f4);
    
        }
    }
    
    

1.2 File类常用方法

绝对路径和相对路径

  • 绝对路径:从盘符开始的路径,这是一个完整的路径。

  • 相对路径相对于项目目录的路径,这是一个便捷的路径,开发中经常使用

    • 生活中的例子:
      • 你在广东省深圳市宝安区留仙二路中粮商务公园3栋1308教室, 你对象在中粮商务公园楼下
      • 绝对路径:广东省深圳市宝安区留仙二路中粮商务公园3栋1308教室
      • 相对路径:3栋1308教室
    • 程序中的例子: 文件在G:\szitheima119\day10\aaa\a.txt
      • 绝对路径: G:\szitheima119\day10\aaa\a.txt
      • 相对路径: day10\aaa\a.txt
  • 举例:

    /**
     * Created by PengZhiLin on 2021/8/10 9:27
     */
    public class Test {
        public static void main(String[] args) {
            // 绝对路径
            File f1 = new File("G:\\szitheima119\\day10\\aaa\\a.txt");
            // 相对路径
            File f2 = new File("day10\\aaa\\a.txt");
            System.out.println(f1.length()+","+f2.length());// 6,6
        }
    }
    
    

获取功能的方法

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

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

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

  • public long length() :返回由此File表示的文件的长度。 不能获取目录的长度。

    方法演示,代码如下:

    /**
     * Created by PengZhiLin on 2021/8/10 9:43
     */
    public class Test {
        public static void main(String[] args) {
            // 创建File对象,表示G:\szitheima119\day10\aaa\a.txt
            File f1 = new File("G:\\szitheima119\\day10\\aaa\\a.txt");
            File f2 = new File("day10\\aaa\\a.txt");
    
            //- `public String getAbsolutePath() ` :返回此File的绝对路径名字符串。
            System.out.println("绝对路径:" + f1.getAbsolutePath());
            System.out.println("绝对路径:" + f2.getAbsolutePath());
    
            //- ` public String getPath() ` :将此File转换为路径名字符串。 **构造路径**
            System.out.println("构造路径:" + f1.getPath());
            System.out.println("构造路径:" + f2.getPath());
    
            //- `public String getName()`  :返回由此File表示的文件或目录的名称。
            File f3 = new File("day10\\aaa");
            System.out.println("文件名:" + f2.getName());
            System.out.println("文件夹名:" + f3.getName());
    
            //- `public long length()`  :返回由此File表示的文件的长度。 **不能获取目录的长度。**
            System.out.println("文件的字节大小:"+f2.length());// 6
            System.out.println("文件夹的字节大小:"+f3.length());// 0
    
        }
    }
    
    

判断功能的方法

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

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

  • public boolean isFile() :此File表示的是否为文件。

  • 注意: 如果File对象表示的路径不存在,以上三个方法的返回值都是false

    方法演示,代码如下:

    /**
     * Created by PengZhiLin on 2021/8/10 9:48
     */
    public class Test {
        public static void main(String[] args) {
            // 创建File对象
            File f1 = new File("day10\\aaa\\a.txt");// 存在的文件
            File f2 = new File("day10\\aaa");// 存在的文件夹
            File f3 = new File("day10\\bbb");// 不存在的文件夹
    
            //- `public boolean exists()` :此File表示的文件或目录是否实际存在。
            System.out.println("f1表示的文件是否真实存在:"+f1.exists());// true
            System.out.println("f2表示的文件夹是否真实存在:"+f2.exists());// true
            System.out.println("f3表示的文件夹是否真实存在:"+f3.exists());// false
    
            //- `public boolean isDirectory()` :此File表示的是否为目录。
            System.out.println("f1是否是文件夹"+f1.isDirectory());// false
            System.out.println("f2是否是文件夹"+f2.isDirectory());// true
            System.out.println("f3是否是文件夹"+f3.isDirectory());// false
    
            //- `public boolean isFile()` :此File表示的是否为文件。
            System.out.println("f1是否是文件"+f1.isFile());// true
            System.out.println("f2是否是文件"+f2.isFile());// false
            System.out.println("f3是否是文件"+f3.isFile());// false
        }
    }
    
    

创建删除功能的方法

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

  • public boolean delete() :删除由此File表示的文件或目录。 删除文件,或者删除空文件夹, 不能删除非空文件夹

  • public boolean mkdir() :创建由此File表示的目录。

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

    方法演示,代码如下:

    /**
     * Created by PengZhiLin on 2021/8/10 9:54
     */
    public class Test {
        public static void main(String[] args) throws IOException {
            //- `public boolean createNewFile()` :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
            // 创建File对象
            /*File f1 = new File("day10\\aaa\\b.txt");
            boolean res1 = f1.createNewFile();
            System.out.println("res1:"+res1);*/
    
    
            //- `public boolean delete()` :删除由此File表示的文件或目录。  **删除文件,或者删除空文件夹, 不能删除非空文件夹**
            /*File f2 = new File("day10\\aaa\\b.txt");
            boolean res2 = f2.delete();
            System.out.println("res2:" + res2);*/
    
            /*File f2 = new File("day10\\aaa");
            boolean res2 = f2.delete();
            System.out.println("res2:" + res2);*/
    
            //- `public boolean mkdir()` :创建由此File表示的目录。
            /*File f3 = new File("day10\\aaa\\bbb");
            boolean res3 = f3.mkdir();
            System.out.println("res3:" + res3);*/
    
            //- `public boolean mkdirs()` :创建由此File表示的目录,包括任何必需但不存在的父目录。
            /*File f4 = new File("day10\\aaa\\ccc\\ddd\\eee\\fff");
            boolean res4 = f4.mkdirs();
            System.out.println("res4:" + res4);*/
    
    
            // 特殊:
            /*File f1 = new File("day10\\aaa\\ddd");
            boolean res1 = f1.createNewFile();// 创建一个ddd文件,文件类型就是文件类型,没有具体的文件类型
            System.out.println("res1:"+res1);*/
    
            /*File f3 = new File("day10\\aaa\\c.txt");
            boolean res3 = f3.mkdir();
            System.out.println("res3:" + res3);*/
        }
    }
    
    

遍历目录方法

  • public String[] list() :获取File目录中的所有子文件或子目录的名称。

  • public File[] listFiles() :获取File目录中的所有子文件或子目录的路径。

  • 结论; 循环遍历返回的数组之前,建议做非空判断,避免空指针异常

    /**
     * Created by PengZhiLin on 2021/8/10 10:09
     */
    public class Test {
        public static void main(String[] args) {
            // 创建File对象
            File f1 = new File("day10\\aaa");
    
            //- `public String[] list()` :获取File目录中的所有子文件或子目录的名称。
            String[] arr1 = f1.list();
            for (String name : arr1) {
                System.out.println(name);
            }
            System.out.println("---------------");
    
            //- `public File[] listFiles()` :获取File目录中的所有子文件或子目录的路径。
            File[] arr2 = f1.listFiles();
            for (File file : arr2) {
                System.out.println(file);
            }
    
            System.out.println("---------------");
            // 创建File对象
            File f2 = new File("H:\\System Volume Information");
            File[] arr3 = f2.listFiles();
            System.out.println(arr3);
            /*for (File file : arr3) {// 报空指针异常
                System.out.println(file);
            }*/
    
            // 循环遍历返回的数组之前,建议做非空判断,避免空指针异常**
            if (arr3 != null){
                for (File file : arr3) {
                    System.out.println(file);
                }
            }
    
        }
    }
    
    

第二章 递归

2.1 递归的概述

  • 概述:

    • 生活中的递归: 放羊-->赚钱-->盖房子-->娶媳妇-->生娃-->放羊-->赚钱-->盖房子-->娶媳妇-->生娃-->放羊...
    • 程序中的递归: 方法自己调用自己
    • 注意:
      • 1.递归没有出口,就会报栈内存溢出错误StackOverflowError
      • 2.出口不能太晚了,否则也会报栈内存溢出错误StackOverflowError
  • 案例

    /**
     * Created by PengZhiLin on 2021/8/10 10:21
     */
    public class Test {
        public static void main(String[] args) {
            /*
                递归: 方法自己调用自己
                注意:
                    1.递归一定要有出口,否则会报栈内存溢出错误StackOverflowError
                    2.递归出口太晚了,也会出现栈内存溢出错误StackOverflowError
             */
            method();
        }
    
        static int count = 0;
    
        public static void method(){
            // 出口
            if (count == 4000){
                return;
            }
    
            count++;
            System.out.println("method....");
            // 递归
            method();
        }
    }
    
    

2.2 递归累和

需求

  • 定义一个方法,使用递归计算1 ~ n的累加和

分析

  • 出口: 什么时候结束递归
  • 规律: 什么时候递归
  • 定义一个方法,用来计算一个数的累加和
    • 1的累加和: 1
    • 2的累加和: 1 + 2
    • 3的累加和: 1 + 2 + 3
    • ...
    • n的累加和: 1 + 2 ....+n
    • n的累加和: n + (n-1)的累加和

实现

/**
 * Created by PengZhiLin on 2021/8/10 10:40
 */
public class Test {
    public static void main(String[] args) {
        System.out.println(getSum(5));
    }

    /**
     * 计算一个数的累加和
     * @param n
     * @return
     */
    public static int getSum(int n){
        // 出口
        if(n == 1){
            return 1;
        }

        // 递归
        return n + getSum(n-1);
    }
}

代码执行图解

2.3 递归求阶乘

需求

  • 递归计算n的阶乘

分析

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

n的阶乘 = n * (n1)的阶乘,所以可以把阶乘的操作定义成一个方法,递归调用。

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

实现


/**
 * Created by PengZhiLin on 2021/8/10 10:50
 */
public class Test {
    public static void main(String[] args) {
        System.out.println(jieCheng(5));
    }

    /**
     * 计算一个数的阶乘
     * @param n
     * @return
     */
    public static int jieCheng(int n){
        // 出口
        if (n == 1){
            return 1;
        }

        // 递归
       return n * jieCheng(n - 1);
    }
}

2.4 文件搜索

需求

  • 输出day10目录中的所有.java文件的绝对路径。

分析

  1. 定义一个方法,用来获取day10下面的所有.java文件
    1. 获取文件夹下的所有子文件和子文件夹
    2. 循环遍历所有子文件和子文件夹
    3. 在循环中,判断遍历出来的是文件还是文件夹:
    4. 如果是文件,就判断文件名是否以.java结尾
    5. 如果是文件夹,就递归

实现


/**
 * Created by PengZhiLin on 2021/8/10 10:55
 */
public class Test {
    public static void main(String[] args) {
        findJavaFile(new File("day10"));
    }

    //定义一个方法,用来获取day10下面的所有.java文件
    public static void findJavaFile(File file) {
        //1.  获取文件夹下的所有子文件和子文件夹
        File[] arr = file.listFiles();

        //2.  循环遍历所有子文件和子文件夹
        if (arr != null){
            for (File f : arr) {
                //3.  在循环中,判断遍历出来的是文件还是文件夹:
                if (f.isFile() && f.getName().endsWith(".java")) {
                    //4.  如果是文件,就判断文件名是否以.java结尾
                    System.out.println(f.getAbsolutePath());
                }
                //5.  如果是文件夹,就递归
                if (f.isDirectory()){
                    findJavaFile(f);
                }
            }
        }

    }
}

第三章 IO概述

IO的概述

  • I : Input 输入 从其他存储设备读数据到内存中就是输入
  • O : Output 输出 从内存中写数据到其他存储设备

IO的分类

  • 按照类型分: 字节流和字符流
    • 字节流:
      • 字节输入流: 以字节为基本单位,进行读数据
      • 字节输出流: 以字节为基本单位,进行写数据
    • 字符流:
      • 字符输入流: 以字符为基本单位,进行读数据
      • 字符输出流: 以字符为基本单位,进行写数据
  • 按流向分: 输入流和输出流
  • 输入流: 读数据
    • 字节输入流: 以字节为基本单位,进行读数据
    • 字符输入流: 以字符为基本单位,进行读数据
    • 输出流: 写数据
      • 字节输出流: 以字节为基本单位,进行写数据
      • 字符输出流: 以字符为基本单位,进行写数据

IO的顶层父类

  • 字节流:
    • 字节输入流: 顶层父类是InputStream抽象类
    • 字节输出流: 顶层父类是OutputStream抽象类
  • 字符流:
    • 字符输入流: 顶层父类是Reader抽象类
    • 字符输出流: 顶层父类是Writer抽象类

注意事项

  • utf8编码一个中文占3个字节,gbk编码一个中文占2个字节

  • idea默认编码是utf8

  • 如果存储和解析的编码不一致就会乱码

第四章 字节流

4.1 字节输出流【OutputStream】

OutputStream类的概述

  • 概述: java.io.OutputStream 抽象类是表示字节输出流的所有类的父类

  • 作用:

    • 将指定的字节信息写出到目的地文件中。
    • 它定义了所有字节输出流的基本共性功能方法。(所有类都继承了OutputStream)

OutputStream类的常用方法

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public abstract void write(int b) :写出一个字节数据到目的地文件中。
  • public void write(byte[] b):将 b.length字节写出到目的地文件中。
  • public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。

小贴士:

close方法,当完成流的操作时,必须调用此方法,释放系统资源。

4.2 FileOutputStream类

  • 概述: java.io.FileOutputStream类继承了OutputStream类,所以也是表示字节输出流,可以用来写出字节数据到目的地文件中.

  • 构造方法

    • public FileOutputStream(File fPath) 创建一个字节输出流对象,关联的文件通过参数来指定

    • public FileOutputStream(String path) 创建一个字节输出流对象,关联的文件通过参数来指定

    • 注意:

      • 如果关联的文件不存在,就会自动创建一个新的空文件
      • 如果关联的文件存在,就会清空源文件中的数据
    • 案例:

      /**
       * Created by PengZhiLin on 2021/8/10 11:15
       */
      public class Test {
          public static void main(String[] args) throws FileNotFoundException {
              //- `public FileOutputStream(File fPath) 创建一个字节输出流对象,关联的文件通过参数来指定`
              //- `public FileOutputStream(String path) 创建一个字节输出流对象,关联的文件通过参数来指定`
              //注意:
              //- 如果关联的文件不存在,就会自动创建一个新的空文件
              //- 如果关联的文件存在,就会清空源文件中的数据
              //FileOutputStream fos1 = new FileOutputStream("day10\\bbb\\a.txt");
              FileOutputStream fos2 = new FileOutputStream(new File("day10\\bbb\\a.txt"));
      
          }
      }
      
      
  • 写出数据的方法

    • 写一个字节: public void write(int b) :写出一个字节数据到目的地文件中。

      /**
       * Created by PengZhiLin on 2021/8/10 11:18
       */
      public class Test1_写一个字节 {
          public static void main(String[] args) throws Exception {
              // 1.创建字节输出流对象,关联目的地文件路径
              FileOutputStream fos = new FileOutputStream("day10\\bbb\\a.txt");
      
              // 2.写一个字节到文件中
              fos.write(97);
              fos.write(98);
      
              // 3.关闭流,释放资源
              fos.close();
          }
      }
      文件内容: ab
      
    • 写字节数组: public void write(byte[] b) :将 b.length字节写出到目的地文件中。

      /**
       * Created by PengZhiLin on 2021/8/10 11:31
       */
      public class Test2_写字节数组 {
          public static void main(String[] args) throws Exception {
              // 1.创建字节输出流对象,关联目的地文件路径
              FileOutputStream fos = new FileOutputStream("day10\\bbb\\b.txt");
      
              // 2.创建字节数组,存储字节数据
              byte[] bys = {97,98,99,100,101,102};
      
              // 3.写字节数组中的字节数据到目的地文件中
              fos.write(bys);
      
              // 4.关闭流,释放资源
              fos.close();
      
          }
      }
      
      文件内容: abcdef
      
    • 写指定长度字节数组: public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。

      /**
       * Created by PengZhiLin on 2021/8/10 11:35
       */
      public class Test3_写指定长度字节数组 {
          public static void main(String[] args) throws Exception {
              // 1.创建字节输出流对象,关联目的地文件路径
              FileOutputStream fos = new FileOutputStream("day10\\bbb\\c.txt");
      
              // 2.创建字节数组,存储字节数据
              byte[] bys = {97, 98, 99, 100, 101, 102};
      
              // 3.写指定长度字节数组
              fos.write(bys,2,3);
      
              // 4.关闭流,释放资源
              fos.close();
      
          }
      }
      文件内容: cde
      
    • 追加续写---->创建字节输出流对象的时候,不要清空源文件中的数据

      • public FileOutputStream(File path,boolean append) 创建一个字节输出流对象,关联的文件通过参数来指定

      • public FileOutputStream(String path,boolean append) 创建一个字节输出流对象,关联的文件通过参数来指定

      • 注意:

        • 如果关联的文件不存在,就会自动创建一个新的空文件
        • 如果关联的文件存在,并且第二个参数设置为true,就不清空源文件中的数据,否则就清空(false)
      • 案例

        /**
         * Created by PengZhiLin on 2021/8/10 11:39
         */
        public class Test4_追加续写 {
            public static void main(String[] args) throws Exception{
                // 1.创建字节输出流对象,关联目的地文件路径
                //FileOutputStream fos = new FileOutputStream("day10\\bbb\\d.txt",false);// 清空
                FileOutputStream fos = new FileOutputStream("day10\\bbb\\d.txt",true);// 追加续写
        
                // 2.写字节数据
                fos.write('d');
                fos.write('e');
                fos.write('f');
        
                // 3.关闭流,释放资源
                fos.close();
            }
        }
        原文件内容: abc
        执行程序后: abcdef
        
    • 写出换行

      • 回车符\r和换行符\n

        • 回车符:回到一行的开头(return)。
        • 换行符:下一行(newline)。
      • 系统中的换行:

        • Windows系统里,每行结尾是 回车+换行 ,即\r\n
        • Unix系统里,每行结尾只有 换行 ,即\n
        • Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一。
        /**
         * Created by PengZhiLin on 2021/8/10 11:45
         */
        public class Test {
            public static void main(String[] args) throws Exception{
                /*
                    静夜思
                    床前明月光
                    疑是地上霜
                    举头望明月
                    低头思故乡
                 */
                // 1.创建字节输出流对象,关联目的地文件路径
                FileOutputStream fos = new FileOutputStream("day10\\bbb\\e.txt");
        
                // 2.写数据
                fos.write("静夜思".getBytes());
                fos.write("\r\n".getBytes());
        
                fos.write("床前明月光".getBytes());
                fos.write("\r\n".getBytes());
        
                fos.write("疑是地上霜".getBytes());
                fos.write("\r\n".getBytes());
        
                fos.write("举头望明月".getBytes());
                fos.write("\r\n".getBytes());
        
                fos.write("低头思故乡".getBytes());
        
                // 3.关闭流,释放资源
                fos.close();
            }
        }
        文件内容:
        静夜思
        床前明月光
        疑是地上霜
        举头望明月
        低头思故乡
        

4.3 字节输入流【InputStream】

InputStream类的概述

概述: java.io.InputStream 抽象类是表示字节输入流的所有类的超类,

作用:

1. 可以读取字节信息到内存中。
2. 它定义了字节输入流的基本共性功能方法。

InputStream类的常用方法

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
  • public abstract int read(): 读一个字节。
  • public int read(byte[] b): 读一个字节数组

小贴士:

close方法,当完成流的操作时,必须调用此方法,释放系统资源。

4.4 FileInputStream类

  • 概述: java.io.FileInputStream类继承InputStream类,也表示字节输入流,可以用来读字节数据到内存中.

  • 构造方法

    • public FileInputStream(File fPath); 创建字节输入流对象,通过参数关联数据源文件路径.

    • public FileInputStream(String path); 创建字节输入流对象,通过参数关联数据源文件路径.

    • 注意:

      • 如果关联的文件路径不存在,就会报文件找不到异常
      /**
       * Created by PengZhiLin on 2021/8/10 11:56
       */
      public class Test1 {
          public static void main(String[] args) throws Exception{
              //- `public FileInputStream(File fPath); 创建字节输入流对象,通过参数关联数据源文件路径.`
              FileInputStream fis1 = new FileInputStream(new File("day10\\ccc\\a.txt"));
      
              //- `public FileInputStream(String path); 创建字节输入流对象,通过参数关联数据源文件路径.`
              FileInputStream fis2 = new FileInputStream("day10\\ccc\\a.txt");
      
              // 注意:如果文件路径不存在,就会报文件找不到异常
              //FileInputStream fis3 = new FileInputStream("day10\\ccc\\b.txt");// 报文件找不到异常
          }
      }
      
      
  • 读取数据

    • 读一个字节:public int read(): 读一个字节并返回字节数据,读到文件的末尾返回-1。

      文件中的内容: abcde
      /**
       * Created by PengZhiLin on 2021/8/10 12:01
       */
      public class Test1_读一个字节 {
          public static void main(String[] args) throws Exception{
              // 读一个字节:`public int read()`: 读一个字节并返回字节数据,读到文件的末尾返回-1。
              // 1.创建字节输入流对象,关联数据源文件路径
              FileInputStream fis = new FileInputStream("day10\\ccc\\a.txt");
      
              // 2.读数据
              int b1 = fis.read();
              System.out.println("b1:"+b1);// 97
      
              int b2 = fis.read();
              System.out.println("b2:"+b2);// 98
      
              int b3= fis.read();
              System.out.println("b3:"+b3);// 99
      
              int b4 = fis.read();
              System.out.println("b4:"+b4);// 100
      
              int b5 = fis.read();
              System.out.println("b5:"+b5);// 101
      
              int b6 = fis.read();
              System.out.println("b6:"+b6);// -1
      
              // 3.关闭流,释放资源
              fis.close();
      
          }
      }
      
      
      • 发现可以使用循环改进读取数据的代码

        public class Test2_读一个字节 {
            public static void main(String[] args) throws Exception {
                // 读一个字节:`public int read()`: 读一个字节并返回字节数据,读到文件的末尾返回-1。
                // 1.创建字节输入流对象,关联数据源文件路径
                FileInputStream fis = new FileInputStream("day10\\ccc\\a.txt");
        
                // 2.读数据
                // 定义int类型的变量,用来存储读取到的字节数据
                int b;
                // 读一个字节数据赋值给b,然后拿b与-1进行比较
                while ((b = fis.read()) != -1) {
                    System.out.println(b);
                }
        
                // 3.关闭流,释放资源
                fis.close();
        
            }
        }
        
        
    • 读一个字节数组: public int read(byte[] b): 读一个字节数组,读到的字节数据存储在byte数组中,返回读取到的字节个数,如果读取到文件的末尾,就返回-1

      /**
       * Created by PengZhiLin on 2021/8/10 12:10
       */
      public class Test3_读一个字节数组 {
          public static void main(String[] args) throws Exception{
              // 1.创建字节输入流对象,关联数据源文件路径
              FileInputStream fis = new FileInputStream("day10\\ccc\\a.txt");
      
              // 2.定义字节数组,用来存储读取到的字节数据
              byte[] bys = new byte[2];
      
              // 3.读字节数组
              int len1 = fis.read(bys);
              System.out.println("读取到的字节个数:"+len1);// 2
              System.out.println("读取到的字节数据:"+ new String(bys,0,len1));//ab
      
              int len2 = fis.read(bys);
              System.out.println("读取到的字节个数:"+len2);// 2
              System.out.println("读取到的字节数据:"+ new String(bys,0,len2));//cd
      
              int len3 = fis.read(bys);
              System.out.println("读取到的字节个数:"+len3);// 1
              System.out.println("读取到的字节数据:"+ new String(bys,0,len3));// ed
      
              int len4 = fis.read(bys);
              System.out.println("读取到的字节个数:"+len4);// -1
              //System.out.println("读取到的字节数据:"+ new String(bys));// ed
      
              // 4.关闭流,释放资源
              fis.close();
      
          }
      }
      
      
      • 循环改进:

        
        /**
         * Created by PengZhiLin on 2021/8/10 12:10
         */
        public class Test4_读一个字节数组 {
            public static void main(String[] args) throws Exception {
                // 1.创建字节输入流对象,关联数据源文件路径
                FileInputStream fis = new FileInputStream("day10\\ccc\\a.txt");
        
                // 2.定义字节数组,用来存储读取到的字节数据
                byte[] bys = new byte[2];
                // 2.定义int变量,用来存储读取到的字节个数
                int len;
        
                // 3.读字节数组
         
                // 把读取到的字节数据存储到bys数组中,然后返回读取到的字节个数,再拿读取到的字节个数与-1进行比较
                while ((len = fis.read(bys)) != -1) {
                    System.out.println("读取到的字节数据:" + new String(bys, 0, len));
                }
        
                // 4.关闭流,释放资源
                fis.close();
        
            }
        }
        
        

4.5 拷贝图片练习

需求

  • 使用字节流拷贝一张图片

分析

1588696319583

一次读写一个字节拷贝文件:
	1.创建字节输入流对象,关联数据源文件路径
    2.创建字节输出流对象,关联目的地文件路径
    3.定义一个int变量,用来存储读取到的字节数据
    4.循环读取字节数据
    5.在循环中,写出字节数据
    6.关闭流,释放资源
        
一次读写一个字节数组拷贝文件:
	1.创建字节输入流对象,关联数据源文件路径
    2.创建字节输出流对象,关联目的地文件路径
    3.定义一个byte数组,用来存储读取到的字节数据
    3.定义一个int变量,用来存储读取到的字节个数
    4.循环读取字节数据
    5.在循环中,写出字节数据
    6.关闭流,释放资源
        

实现

复制图片文件,代码使用演示:


/**
 * Created by PengZhiLin on 2021/8/10 12:26
 */
public class Test1 {
    public static void main(String[] args) throws Exception{
        //	1.创建字节输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day10\\ccc\\hb1.jpg");

        //  2.创建字节输出流对象,关联目的地文件路径
        FileOutputStream fos = new FileOutputStream("day10\\bbb\\hbCopy5.jpg");

        //  3.定义一个int变量,用来存储读取到的字节数据
        int b;

        //  4.循环读取字节数据
        while ((b = fis.read()) != -1) {
            //  5.在循环中,写出字节数据
            fos.write(b);
        }

        //  6.关闭流,释放资源
        fos.close();
        fis.close();
    }
}

/**
 * Created by PengZhiLin on 2021/8/10 12:26
 */
public class Test2 {
    public static void main(String[] args) throws Exception{
        //	1.创建字节输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day10\\ccc\\hb1.jpg");

        //  2.创建字节输出流对象,关联目的地文件路径
        FileOutputStream fos = new FileOutputStream("day10\\bbb\\hbCopy3.jpg");

        //  3.定义一个byte数组,用来存储读取到的字节数据
        byte[] bys = new byte[8192];

        //  3.定义一个int变量,用来存储读取到的字节个数
        int len;

        //  4.循环读取字节数据
        while ((len = fis.read(bys)) != -1){
            // 5.写出数据
            fos.write(bys,0,len);
        }


        //  6.关闭流,释放资源
        fos.close();
        fis.close();
    }
}

第五章 字符流

5.1 字节流读文本文件的问题

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

/**
 * Created by PengZhiLin on 2021/8/10 14:46
 */
public class Test {
    public static void main(String[] args) throws Exception{
        // 1.创建字节输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day10\\ddd\\a.txt");
        
        // 2.定义一个int类型的变量,用来存储读取到的字节数据
        int b;

        // 3.循环读数据
        while ((b = fis.read()) != -1){
            System.out.println((char) b);// 乱码
        }

        // 4.关闭流,释放资源
        fis.close();
    }
}

5.2 字符输入流【Reader】

字符输入流Reader类的概述

概述: java.io.Reader抽象类是表示用于读取字符流的所有类的超类

作用:

1. 可以读取字符信息到内存中。
2. 它定义了字符输入流的基本共性功能方法。

字符输入流Reader类的常用方法

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。
  • public int read(): 从输入流读取一个字符,读取文件的末尾返回-1。
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中,返回读取到的字符个数,读取到文件的末尾返回-1 。

5.3 FileReader类

  • 概述: java.io.FileReader类继承Reader类,也表示字符输入流,可以用读字符数据到内存中

  • 构造方法:

    • public FileReader(File fPath);创建字符输入流对象,通过参数关联数据源文件路径

    • public FileReader(String Path);创建字符输入流对象,通过参数关联数据源文件路径

    • 注意:

      • 如果传入的文件路径不存在,就报文件找不到异常FileNotFountException
    • 案例:

      /**
       * Created by PengZhiLin on 2021/8/10 14:54
       */
      public class Test {
          public static void main(String[] args) throws Exception {
              /*
                  - `public FileReader(File fPath);创建字符输入流对象,通过参数关联数据源文件路径`
                  - `public FileReader(String Path);创建字符输入流对象,通过参数关联数据源文件路径`
                  - 注意:
                    - 如果传入的文件路径不存在,就报文件找不到异常FileNotFountException
               */
              // 创建字符输入流对象,关联数据源文件路径
              FileReader fr1 = new FileReader(new File("day10\\ddd\\a.txt"));
              FileReader fr2 = new FileReader("day10\\ddd\\a.txt");
      
              // 注意:
              //FileReader fr3 = new FileReader("day10\\ddd\\aa.txt");// 报文件找不到异常FileNotFoundException
      
          }
      }
      
      
  • 读数据的方法

    • 读一个字符:public int read(): 从输入流读取一个字符,读取文件的末尾返回-1。

      /**
       * Created by PengZhiLin on 2021/8/10 14:56
       */
      public class Test1_读一个字符 {
          public static void main(String[] args) throws Exception{
              // 读一个字符:`public int read()`: 从输入流读取一个字符,读取文件的末尾返回-1。
              // 1.创建字符输入流对象,关联数据源文件路径
              FileReader fr = new FileReader("day10\\ddd\\a.txt");
      
              // 2.定义一个int类型的变量,用来存储读取到的字符数据
              int c;
      
              // 3.循环读字符数据
              while ((c = fr.read()) != -1){
                  System.out.println((char) c);
              }
      
              // 4.关闭流,释放资源
              fr.close();
      
          }
      }
      
      
    • 读一个字符数组:public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中,返回读取到的字符个数,读取到文件的末尾返回-1 。

      /**
       * Created by PengZhiLin on 2021/8/10 15:00
       */
      public class Test2_读一个字符数组 {
          public static void main(String[] args) throws Exception{
              /*
                  读一个字符数组:`public int read(char[] cbuf)`: 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中,返回读取到的字符个数,读取到文件的末尾返回-1 。
               */
              // 1.创建字符输入流对象,关联数据源文件路径
              FileReader fr = new FileReader("day10\\ddd\\a.txt");
      
              // 2.定义一个字符数组,用来存储读取到的字符数据
              char[] chs = new char[3];
      
              // 2.定义一个int变量,用来存储读取到的字符个数
              int len;
      
              // 3.循环读
              while ((len = fr.read(chs)) != -1){
                  System.out.println("把读到的字符数据转换为字符串:"+new String(chs,0,len));
              }
      
              // 4.关闭流,释放资源
              fr.close();
      
          }
      }
      
      

5.4 字符输出流【Writer】

字符输出流Writer类的概述

概述: java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,

作用:

1.  **将指定的字符信息写出到目的地**。
2.  它定义了字符输出流的基本共性功能方法。

字符输出流Writer类的常用方法

  • public abstract void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public abstract void flush() :刷新此输出流并强制任何缓冲的输出字符被写出。
  • public void write(int c) :写出一个字符。
  • public void write(char[] cbuf):将 b.length字符从指定的字符数组写出此输出流。
  • public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
  • public void write(String str) :写出一个字符串。
  • public void write(String str,int off,int len) :写出一个字符串的一部分。

5.5 FileWriter类

  • 概述: java.io.FileWriter类继承Writer类,也表示一个字符输出流,可以用来写出字符数据到目的地文件中

  • 构造方法:

    • public FileWriter(File fpath); 创建字符输出流对象,通过参数关联目的地文件路径

    • public FileWriter(String path); 创建字符输出流对象,通过参数关联目的地文件路径

    • public FileWriter(File fpath,boolean append); 创建字符输出流对象,通过参数关联目的地文件路径

    • public FileWriter(String path,boolean append); 创建字符输出流对象,通过参数关联目的地文件路径

    • 注意:

      • 以上4个构造方法, 如果路径表示的文件不存在,就会自动创建一个新的空文件

      • 前面2个构造方法,如果路径表示的文件存在,就会清空文件中的数据

      • 后面2个构造方法,如果第二个参数为true,就不清空文件中的数据,如果为false,就清空文件中的数据

      /**
       * Created by PengZhiLin on 2021/8/10 15:09
       */
      public class Test {
          public static void main(String[] args) throws Exception{
              // 1.创建字符输出流对象,关联目的地文件路径
              FileWriter fw1 = new FileWriter("day10\\eee\\a.txt");// 会清空文件中的数据
              FileWriter fw2 = new FileWriter("day10\\eee\\b.txt",true);// 不会清空文件中的数据
      
          }
      }
      
      
  • 写出数据:

    • 写一个字符: public void write(int c) :写出一个字符。

      /**
       * Created by PengZhiLin on 2021/8/10 15:13
       */
      public class Test1_写一个字符 {
          public static void main(String[] args) throws Exception{
              //**写一个字符**: `public void write(int c)` :写出一个字符。
              // 创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\eee\\c.txt");
      
              // 写一个字符
              fw.write('a');
              fw.write(98);
              fw.write('中');
      
              // 关闭流,释放资源
              fw.close();
      
          }
      }
      文件中的内容:
      ab中
      
    • 写字符数组:public void write(char[] cbuf):将 b.length字符从指定的字符数组写出此输出流。

      /**
       * Created by PengZhiLin on 2021/8/10 15:15
       */
      public class Test2_写一个字符数组 {
          public static void main(String[] args) throws Exception{
              // 写字符数组:`public void write(char[] cbuf)`:将 b.length字符从指定的字符数组写出此输出流。
              // 1.创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\eee\\d.txt");
      
              // 2.定义一个字符数组,并存储字符
              char[] chs = {'a','b','c','中','国'};
      
              // 3.写字符数组
              fw.write(chs);
      
              // 4.关闭流,释放资源
              fw.close();
      
          }
      }
      文件内容:
      abc中国
      
    • 写指定长度字符数组: public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。

      /**
       * Created by PengZhiLin on 2021/8/10 15:15
       */
      public class Test3_写一个字符数组 {
          public static void main(String[] args) throws Exception{
              // 写字符数组:`public abstract void write(char[] b, int off, int len)` :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
              // 1.创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\eee\\e.txt");
      
              // 2.定义一个字符数组,并存储字符
              char[] chs = {'a','b','c','中','国'};
      
              // 3.写字符数组中的中国2个字符
              fw.write(chs,3,2);
      
              // 4.关闭流,释放资源
              fw.close();
      
          }
      }
      文件内容:
      中国
      
    • 写字符串:public void write(String str) :写出一个字符串。

      /**
       * Created by PengZhiLin on 2021/8/10 15:19
       */
      public class Test4_写字符串 {
          public static void main(String[] args) throws Exception{
              //写字符串:`public void write(String str)` :写出一个字符串。
              // 1.创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\eee\\f.txt");
      
              // 2.写字符串
              fw.write("itheima-黑马程序员");
      
              // 3.关闭流,释放资源
              fw.close();
          }
      
      }
      
      
    • 写指定长度字符串: public void write(String str,int off,int len) :写出一个字符串的一部分。

      /**
       * Created by PengZhiLin on 2021/8/10 15:19
       */
      public class Test5_写字符串 {
          public static void main(String[] args) throws Exception{
              //写字符串:`public void write(String str,int off,int len)` :写出一个字符串的一部分。
              // 1.创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\eee\\g.txt");
      
              // 2.写字符串
              fw.write("itheima-黑马程序员",8,5);
      
              // 3.关闭流,释放资源
              fw.close();
          }
      
      }
      
      
  • 关闭和刷新

    • public abstract void close() :关闭此输出流并释放与此流相关联的任何系统资源。

    • public abstract void flush() :刷新此输出流并强制任何缓冲的输出字符被写出。

    • 区别:

      • 关闭: 关闭流之前会刷新,关闭之后流就不能再使用了

      • 刷新: 刷新之后流还可以继续使用

        /**
         * Created by PengZhiLin on 2021/8/10 15:23
         */
        public class Test6_关闭和刷新 {
            public static void main(String[] args) throws Exception{
                /*
                    - `public abstract void close()` :关闭此输出流并释放与此流相关联的任何系统资源。
                    - `public abstract void flush() ` :刷新此输出流并强制任何缓冲的输出字符被写出。
                    区别:
                        - 关闭: 关闭流之前会刷新,关闭之后流就不能再使用了
                        - 刷新: 刷新之后流还可以继续使用
                 */
                // 1.创建字符输出流对象,关联目的地文件路径
                FileWriter fw = new FileWriter("day10\\eee\\h.txt");
        
                // 2.写数据
                fw.write('刷');
        
                // 刷新一下
                fw.flush();
        
                //写数据
                fw.write('新');
                fw.flush();
        
                // 关闭
                fw.write('关');
                fw.close();
        
                fw.write('闭');// 报异常IOException: Stream closed
                fw.close();
        
        
            }
        }
        
        

总结

必须练习:
	1.一次读写一个字节拷贝文件
    2.一次读写一个字节数组拷贝文件
    3.一次读写一个字符拷贝 文本文件
    4.一次读写一个字符数组拷贝 文本文件
    以上4个案例必须写5遍----> 20遍---->脱离笔记,能够自己独立写出来
    5.追加续写
    6.搜索指定类型的文件--->递归,File类


- 能够说出File对象的创建方式
    public File(String pathname);
    public File(String parent,String child);
    public File(File parent,String child);

- 能够使用File类常用方法
    public String getAbsolutePath() :返回此File的绝对路径名字符串。
    public String getPath() :获取构造路径(构造方法中传入的路径)
    public String getName()  :返回由此File表示的文件或目录的名称。
    public long length()  :返回由此File表示的文件的字节大小。 不能获取目录的字节大小
    
    public boolean exists() :此File表示的文件或目录是否实际存在。
    public boolean isDirectory() :此File表示的是否为目录。
    public boolean isFile() :此File表示的是否为文件。
    
    public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
    public boolean delete() :删除由此File表示的文件或目录。注意,只能删除空文件夹
    public boolean mkdir() :创建由此File表示的目录。
    public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
    
    public String[] list() :获取File目录中的所有子文件或子目录的名称。
	public File[] listFiles() :获取File目录中的所有子文件或子目录的路径。
    
- 能够辨别相对路径和绝对路径
    相对路径: 相对于项目路径而言的路径
    绝对路径: 以盘符开始的完整路径
        
- 能够遍历文件夹
    listFiles()
        
- 能够解释递归的含义
    方法自己调用自己
    规律--出口
        
- 能够使用递归的方式计算5的阶乘
    public static int jieCheng(int n){
        if(n == 1){return 1;}
        return n * jieCheng(n-1);
    } 
- 能够说出使用递归会内存溢出隐患的原因
    递归没有出口,或者递归的出口太晚了,造成方法没有弹栈,栈就满了
    
- 能够说出IO流的分类和功能
   字节流:以字节为基本单位进行读写数据
   字符流:以字符为基本单位进行读写数据
       
- 能够使用字节输出流写出数据到文件
   FileOutputStream:
		write(int b);----常用  写一个字节
 		write(byte[] bys,int off,int len);----常用 写一个字节数组
            
- 能够使用字节输入流读取数据到程序
   FileInputStream:
		int read(); 读一个字节
        int read(byte[] bys);读一个字节数组
            
- 能够理解读取数据read(byte[] bys)方法的原理
   读取数组长度个字节数据存储到字节数组中,返回读取到的字节个数,如果不够数组长度个字节数据,那么有多少个就读多少个
            
- 能够使用字节流完成文件的复制
    查看笔记思路
    一次读写一个字节拷贝文件
    一次读写一个字节数组拷贝文件
            
- 能够使用FileWriter写数据的5个方法
   write(int len);---- 常用   写一个字符
   write(char[] chs,int off,int len)---- 常用  写一个字符数组         
   
   write(char[] chs);  
   write(String str);
   write(String str,int off,int len)
 
- 能够使用FileReader读数据一次一个字符
     int  read() 读一个字符
- 能够使用FileReader读数据一次一个字符数组
     int  read(char[] chs) 读一个字符数组
       
- 能够说出FileWriter中关闭和刷新方法的区别
      关闭: 关闭流,刷新缓冲区,流不能再使用
      刷新: 刷新缓冲区,流可以继续使用
          
- 能够使用FileWriter写数据实现换行和追加写
    public  FileWriter(String path,boolean append)
    public  FileWriter(File path,boolean append)  
          回车换行--->"\r\n"
          

统计文件夹的字节大小

 /**
     * 统计文件夹的字节大小
     * @param path
     * @return
     */
    public static long getSize(File path) {
        // 获取所有的子文件\子文件夹
        File[] files = path.listFiles();
        // 定义一个变量,用来记录文件夹的字节大小
        long len = 0;
        if (files != null) {
            // 循环遍历
            for (File file : files) {
                if (file.isFile()) {
                    // 如果是文件,就计算字节大小,并累加
                    len += file.length();
                }
                if (file.isDirectory()) {
                    // 如果是文件夹,就递归计算文件夹的字节大小,并和之前的文件夹字节大小累加
                    len += getSize(file);
                }
            }
        }
        // 返回文件夹的字节大小
        return len;
    }

删除非空文件夹

  /**
     * 删除非空文件夹
     *
     * @param f
     */
    public static void delete(File f) {
        // 获取所有的子文件\子文件夹
        File[] arr = f.listFiles();
        if (arr.length != -1) {
            // 循环遍历
            for (File file : arr) {
                if (file.isFile()) {
                    // 如果是文件,就删除
                    file.delete();
                }
                if (file.isDirectory()) {
                    // 如果是文件夹,就递归删除
                    delete(file);
                }
            }
        }
        // 最后结束方法之前,删除当前文件夹
        f.delete();
    }

  
posted on 2022-04-24 23:43  ofanimon  阅读(32)  评论(0编辑  收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css