【File类、递归、IO流、字节流、字符流】

yday10【File类、递归、IO流、字节流、字符流】

今日内容

  • 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对象的创建
  • 构造举例,代码如下:

    public class Test {
        public static void main(String[] args) {
            // 文件或者文件夹真实存在
            // 需求: 创建一个File对象表示G:\szitheima112\day10\aaa\hb.jpg
            // - public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
            File f1 = new File("G:\\szitheima112\\day10\\aaa\\hb.jpg");
    
            // - public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
            //File f2 = new File("G:\\szitheima112\\day10\\aaa", "hb.jpg");
            File f2 = new File("G:\\szitheima112\\day10", "aaa\\hb.jpg");
    
            // - public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。
            File parent = new File("G:\\szitheima112\\day10");
            File f3 = new File(parent, "aaa\\hb.jpg");
    
            System.out.println("f1:" + f1);
            System.out.println("f2:" + f2);
            System.out.println("f3:" + f3);
    
            // 文件或者文件夹不存在
            File f4 = new File("G:\\szitheima112\\day10\\aaa\\a.txt");
            System.out.println("f4:" + f4);
    
            File f5 = new File("G:\\szitheima112\\day10\\aaa\\bbb");
            System.out.println("f5:" + f5);
        }
    }
    

1.2 File类常用方法

绝对路径和相对路径
  • 绝对路径:从盘符开始的路径,这是一个完整的路径。
  • 相对路径相对于项目目录的路径,这是一个便捷的路径,开发中经常使用
  • 举例:
    • 生活中的例子: 你现在在中粮商务公园2栋607,你朋友在中粮商务公园,他问你在哪?

      • 绝对路径: 中国广东省深圳市宝安区留仙二路中粮商务公园2栋607
      • 相对路径: 2栋607
    • 程序中的例子: hb.jpg文件

      • 绝对路径: G:\szitheima112\day10\aaa\hb.jpg
      • 相对路径: day10\aaa\hb.jpg

public class Test {
public static void main(String[] args) {
/*
- 绝对路径:从盘符开始的路径,这是一个完整的路径。
- 相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
*/
// 绝对路径:
File f1 = new File(“G:\szitheima112\day10\aaa\hb.jpg”);

    // 相对路径:
    File f2 = new File("day10\\aaa\\hb.jpg");
}

}
```

获取功能的方法
  • public String getAbsolutePath() :返回此File的绝对路径名字符串。

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

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

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

    方法演示,代码如下:

    public class Test {
        public static void main(String[] args) {
            // 创建File对象
            File f1 = new File("G:\\szitheima112\\day10\\aaa\\hb.jpg");
            File f2 = new File("day10\\aaa\\hb.jpg");
    
            // - 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表示的文件或目录的名称。
            System.out.println("文件名:" + f2.getName());
    
            // - public long length()  :返回由此File表示的文件的长度。 不能获取文件夹的长度。
            System.out.println("文件的字节大小:" + f2.length());// 24666
    
            File f3 = new File("day10\\aaa");
            System.out.println("文件夹的字节大小:" + f3.length());// 0,不能获取文件夹的字节大小,只能获取文件的字节大小
    
        }
    }
    
    
判断功能的方法
  • public boolean exists() :此File表示的文件或目录是否实际存在。

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

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

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

    方法演示,代码如下:

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

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

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

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

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

    方法演示,代码如下:

    public class Test {
        public static void main(String[] args) throws IOException {
            //- public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
            // File f1 = new File("day10\\aaa\\b.txt");
            // boolean res1 = f1.createNewFile();
            // System.out.println("res1:" + res1);
    
            // 注意: 这里会创建一个未知文件类型的bbb文件
            // File f2 = new File("day10\\aaa\\bbb");
            // boolean res2 = f2.createNewFile();
            // System.out.println("res2:" + res2);
    
            //- public boolean delete() :删除由此File表示的文件或目录。  不能删除非空文件夹
            // 注意: delete删除的文件不在回收站,注意使用
            // File f3 = new File("day10\\aaa\\b.txt");
            // boolean res3 = f3.delete();
            // System.out.println("res3:" + res3);
    
            // File f4 = new File("day10\\aaa\\bbb");
            // boolean res4 = f4.delete();
            // System.out.println("res4:" + res4);
    
            // 注意: 不能删除非空文件夹
            //File f5 = new File("day10\\aaa");
            //boolean res5 = f5.delete();
            //System.out.println("res5:" + res5);
    
            // 注意: 可以删除空文件夹
            // File f6 = new File("day10\\bbb");
            // boolean res6 = f6.delete();
            // System.out.println("res6:" + res6);
    
            //- public boolean mkdir() :创建由此File表示的目录。
            // File f7 = new File("day10\\ccc");
            // boolean res7 = f7.mkdir();
            // System.out.println("res7:" + res7);
    
    
            //- public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
            File f8 = new File("day10\\ccc\\aaa\\bbb\\ccc\\ddd");
            boolean res8 = f8.mkdirs();
            System.out.println("res8:" + res8);
    
        }
    }
    
    
遍历目录方法
  • public String[] list() :获取File目录中的所有子文件或子目录的名称。

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

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

    public class Test {
        public static void main(String[] args) {
            // 创建File对象
            File f = new File("day10");
    
            //- public String[] list() :获取File目录中的所有子文件或子目录的名称。
            String[] arr1 = f.list();
            for (String name : arr1) {
                System.out.println("name:" + name);
            }
    
            //- public File[] listFiles() :获取File目录中的所有子文件或子目录的路径。
            File[] arr2 = f.listFiles();
            for (File pathFile : arr2) {
                System.out.println("pathFile:" + pathFile);
            }
            System.out.println("-------");
    
            // 注意: 文件夹不存在,返回null
            File f1 = new File("day10\\bbb");
            File[] arr3 = f1.listFiles();// 返回的null
            // 增强程序的健壮性,应该判断
            if (arr3 != null) {
                for (File file : arr3) {
                    System.out.println("file:" + file);
                }
            }
    
            // 注意: 文件夹没有访问权限,返回null
            File f2 = new File("H:\\System Volume Information");
            File[] arr4 = f2.listFiles();// 返回的null
            // 增强程序的健壮性,应该判断
            if (arr4 != null) {
                for (File file : arr4) {
                    System.out.println("file:" + file);
                }
            }
    
            // 注意: 文件夹为空,返回的是长度为0的数组
            File f3 = new File("day10\\ddd");
            File[] arr5 = f3.listFiles();// 返回的是长度为0的数组
            for (File file : arr5) {
                System.out.println("file:" + file);
            }
        }
    }
    
    

第二章 递归

2.1 递归的概述

  • 概述:

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

    public class Test {
        static int count = 0;
    
        public static void main(String[] args) {
            method1();
        }
    
        public static void method1(){
            count++;
            // 出口--递归结束
            if (count > 10000){
                return;
            }
            // 调用method1方法
            method1();
            System.out.println("method1方法...");
        }
    }
    
    

2.2 递归累和

需求

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

分析

  • 什么时候递归------->规律
  • 什么时候结束递归---->出口
  • n的累加和 = 1 + 2 + 3 + … + n-1 + n
  • n-1的累加和= 1 + 2 + 3 + … + n-1
  • 规律: 一个数的累加和 = 前一个数的累加和 + 当前这个数
  • n的累加和 = n + (n-1)的累加和

实现

public class Test {
    public static void main(String[] args) {
        // 需求:定义一个方法,使用递归计算1 ~ n的累加和
        System.out.println(getSum(5));// 15
    }

    /**
     * 计算一个数的累加和
     * @param n
     * @return sum
     */
    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)!

实现

public class Test {
    public static void main(String[] args) {
        System.out.println(jieCheng(5));// 120
    }

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

        // 规律
        return n * jieCheng(n-1);
    }
}

2.4 文件搜索

需求

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

分析

  1. 获取文件夹中所有的子文件和子文件夹
  2. 循环遍历所有的子文件和子文件夹
  3. 如果遍历出来的是文件,就判断该文件是否是.java文件,如果是就直接打印输出该文件的绝对路径
  4. 如果遍历出来的是文件夹,就递归

实现

public class Test {
    public static void main(String[] args) {
        File file = new File("day10");
        //findFile(file,".java");
        findFile(file,"jpg");
    }

    /**
     * 查找文件
     *
     * @param file
     */
    public static void findFile(File file,String type) {
        //1. 获取文件夹中所有的子文件和子文件夹
        File[] arr = file.listFiles();

        //2. 循环遍历所有的子文件和子文件夹
        if (arr != null) {
            for (File file1 : arr) {
                //3. 如果遍历出来的是文件,就判断该文件是否是.java文件,如果是就直接打印输出该文件的绝对路径
                if (file1.isFile() && file1.getName().endsWith(type)){
                    System.out.println("绝对路径:"+file1.getAbsolutePath());
                }

                //4. 如果遍历出来的是文件夹,就递归
                if (file1.isDirectory()){
                    findFile(file1,type);
                }
            }
        }
    }

    /**
     * 查找文件
     *
     * @param file
     */
    public static void findFile(File file) {
        //1. 获取文件夹中所有的子文件和子文件夹
        File[] arr = file.listFiles();

        //2. 循环遍历所有的子文件和子文件夹
        if (arr != null) {
            for (File file1 : arr) {
                //3. 如果遍历出来的是文件,就判断该文件是否是.java文件,如果是就直接打印输出该文件的绝对路径
                if (file1.isFile() && file1.getName().endsWith(".java")){
                    System.out.println("绝对路径:"+file1.getAbsolutePath());
                }

                //4. 如果遍历出来的是文件夹,就递归
                if (file1.isDirectory()){
                    findFile(file1);
                }
            }
        }
    }
}

第三章 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) 创建一个字节输出流对象,关联的文件通过参数来指定

    • 注意:

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

      public class Test {
          public static void main(String[] args)throws Exception {
              // 文件存在
              FileOutputStream fos1 = new FileOutputStream(new File("day10\\eee\\a.txt"));
      
              // 文件不存在
              FileOutputStream fos2 = new FileOutputStream("day10\\eee\\b.txt");
          }
      }
      
      
  • 写出数据的方法

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

      public class Test1_写一个字节 {
          public static void main(String[] args) throws Exception{
              // 创建字节输出流对象,关联目的地文件路径
              FileOutputStream fos = new FileOutputStream("day10\\eee\\c.txt");
      
              // 写出数据
              fos.write(97);
              fos.write('b');
      
              // 关闭流,释放资源
              fos.close();
          }
      }
      
      文件: ab
      
    • 写字节数组: public void write(byte[] b) :将 b.length字节写出到目的地文件中。

      public class Test2_写字节数组 {
          public static void main(String[] args) throws Exception{
              // 创建字节输出流对象,关联目的地文件路径
              FileOutputStream fos = new FileOutputStream("day10\\eee\\d.txt");
      
              // 写出数据
             byte[] bys = {97,98,99};
             fos.write(bys);
      
              // 关闭流,释放资源
              fos.close();
          }
      }
      文件: abc
      
    • 写指定长度字节数组: public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。

      public class Test3_写指定长度字节数组 {
          public static void main(String[] args) throws Exception{
              // 创建字节输出流对象,关联目的地文件路径
              FileOutputStream fos = new FileOutputStream("day10\\eee\\e.txt");
      
              // 写出数据
             byte[] bys = {97,98,99,100,101,102};
             fos.write(bys,1,3);
      
              // 关闭流,释放资源
              fos.close();
          }
      }
      文件: bcd
      
    • 追加续写---->创建字节输出流对象的时候,不要清空源文件中的数据

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

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

      • 注意:

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

        public class Test4_追加续写 {
            public static void main(String[] args) throws Exception{
                // 创建字节输出流对象,关联目的地文件路径
                FileOutputStream fos = new FileOutputStream("day10\\eee\\a.txt",true);
        
                // 写出数据
                fos.write(97);
        
                // 关闭流,释放资源
                fos.close();
            }
        }
        执行前: abcdef
        执行后: abcdefa
        
    • 写出换行

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

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

        • Windows系统里,每行结尾是 回车+换行 ,即\r\n
        • Unix系统里,每行结尾只有 换行 ,即\n
        • Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一。
        public class Test5_写出换行 {
            public static void main(String[] args) throws Exception{
                /*
                    看这风景美如画
                    本想吟诗赠天下
                    奈何本人没文化
                    一句我操浪好大
                 */
                // 创建字节输出流对象,关联目的地文件路径
                FileOutputStream fos = new FileOutputStream("day10\\eee\\f.txt");
        
                // 写出数据
                fos.write("看这风景美如画\r\n".getBytes());
                fos.write("本想吟诗赠天下\r\n".getBytes());
                fos.write("奈何本人没文化\r\n".getBytes());
                fos.write("一句我操浪好大\r\n".getBytes());
        
                // 关闭流,释放资源
                fos.close();
            }
        }
        

4.3 字节输入流【InputStream】

InputStream类的概述

java.io.InputStream抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。

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); 创建字节输入流对象,通过参数关联数据源文件路径.

    • 注意:

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

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

      public class Test1_读一个字节 {
          public static void main(String[] args) throws Exception {
              // 创建字节输入流对象,关联数据源文件路径
              FileInputStream fis = new FileInputStream("day10\\fff\\a.txt");
      
              // 读数据
              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  --->说明读取到文件的末尾返回的是-1
      
              // 关闭流,释放资源
              fis.close();
      
          }
      }
      文件中的数据是: abcde
      
      • 发现可以使用循环改进读取数据的代码

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

      public class Test3_读一个字节数组 {
          public static void main(String[] args) throws Exception {
              // public int read(byte[] b): 读一个字节数组
      
              // 创建字节输入流对象,关联数据源文件路径
              FileInputStream fis = new FileInputStream("day10\\fff\\a.txt");
      
              // 定义一个byte数组,用来存储读取到的字节数据
              byte[] bys = new byte[2];
      
              // 读数据
              int len1 = fis.read(bys);// 返回的是读取到的字节个数
              System.out.println("len1:" + len1);// len1:2
              System.out.println("bys:" + Arrays.toString(bys));// bys:[97, 98]
      
              int len2 = fis.read(bys);// 返回的是读取到的字节个数
              System.out.println("len2:" + len2);// len2:2
              System.out.println("bys:" + Arrays.toString(bys));// bys:[99, 100]
      
              int len3 = fis.read(bys);// 返回的是读取到的字节个数
              System.out.println("len3:" + len3);// len3:1
              System.out.println("bys:" + Arrays.toString(bys));// bys:[101, 100]
      
              int len4 = fis.read(bys);// 返回的是读取到的字节个数
              System.out.println("len4:" + len4);// len4:-1
              System.out.println("bys:" + Arrays.toString(bys));// bys:[101, 100]
      
              // 关闭流,释放资源
              fis.close();
          }
      }
      
      
      • 循环改进:

        public class Test4_读一个字节数组 {
            public static void main(String[] args) throws Exception {
                // public int read(byte[] b): 读一个字节数组
        
                // 创建字节输入流对象,关联数据源文件路径
                FileInputStream fis = new FileInputStream("day10\\fff\\a.txt");
        
                // 定义一个byte数组,用来存储读取到的字节数据
                byte[] bys = new byte[2];
        
                // 读数据
                // 定义一个int变量,用来存储读取到的字节数据
                int len;
                // 循环读取数据
                while ( (len = fis.read(bys)) != -1){
                    // 读到多少个字节,就把多少个字节转换为字符串
                    System.out.println("bys:"+ new String(bys,0,len));
                }
        
                // 关闭流,释放资源
                fis.close();
        
                // byte[] byes = {97,98,99,100};
                // String str1 = new String(byes,0,2);// 把97,98转换为字符串
            }
        }
        
        

4.5 拷贝图片练习

需求

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

分析

在这里插入图片描述

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

实现

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

public class Test1_一次读写一个字节拷贝文件 {
    public static void main(String[] args) throws Exception {
        // 1.创建字节输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day10\\aaa\\hb.jpg");

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

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

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

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


public class Test2_一次读写一个字节数组拷贝文件 {
    public static void main(String[] args) throws Exception {
        // 1.创建字节输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day10\\aaa\\hb.jpg");

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

        // 3.定义一个byte数组,用来存储读取到的字节数据
        byte[] bys = new byte[8192];// 8192*4+100
        // 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提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

public class Test {
    public static void main(String[] args) throws Exception {
        // 需求: 使用字节流读取day10\ggg\a.txt文件中的数据,打印到控制台
        // 1.创建字节输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day10\\ggg\\a.txt");

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

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

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

    }
}

5.2 字符输入流【Reader】

字符输入流Reader类的概述

java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。

字符输入流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
  • 读数据的方法

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

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

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

5.4 字符输出流【Writer】

字符输出流Writer类的概述

java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字符输出流的基本共性功能方法。

字符输出流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,就清空文件中的数据

      public class Test {
          public static void main(String[] args)throws Exception {
              //FileWriter fw1 = new FileWriter("day10\\hhh\\a.txt");// 清空
              //FileWriter fw2 = new FileWriter("day10\\hhh\\a.txt",true);// 不清空
              FileWriter fw3 = new FileWriter("day10\\hhh\\b.txt");// 创建新的空文件
      
          }
      }
      
      
  • 写出数据:

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

      public class Test1_写一个字符 {
          public static void main(String[] args) throws Exception {
              // 创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\hhh\\c.txt");
      
              // 写出数据
              fw.write(97);
              fw.write('b');
      
              // 关闭流,释放资源
              fw.close();
      
          }
      }
      文件: ab
      
    • 写字符数组:public void write(char[] cbuf):将 b.length字符从指定的字符数组写出此输出流。

      public class Test2_写一个字符数组 {
          public static void main(String[] args) throws Exception {
              // 创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\hhh\\d.txt");
      
              // 写出数据
              char[] chs = {'a','b','c','d','e','f'};
              fw.write(chs);
      
              // 关闭流,释放资源
              fw.close();
      
          }
      }
      // 文件: abcdef
      
    • 写指定长度字符数组: public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。

      public class Test3_写指定长度的字符数组 {
          public static void main(String[] args) throws Exception {
              // 创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\hhh\\e.txt");
      
              // 写出数据
              char[] chs = {'a','b','c','d','e','f'};
              fw.write(chs,0,3);
      
              // 关闭流,释放资源
              fw.close();
      
          }
      }
      // 文件; abc
      
    • 写字符串:public void write(String str) :写出一个字符串。

      public class Test4_写一个字符串 {
          public static void main(String[] args) throws Exception {
              // 创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\hhh\\f.txt");
      
              // 写出数据
              fw.write("看这风景美如画\r\n");
              fw.write("本想吟诗赠天下\r\n");
              fw.write("奈何本人没文化\r\n");
              fw.write("一句我操浪好大\r\n");
      
              // 关闭流,释放资源
              fw.close();
      
          }
      }
      
      
    • 写指定长度字符串: public void write(String str,int off,int len) :写出一个字符串的一部分。

      public class Test5_写指定长度的字符串 {
          public static void main(String[] args) throws Exception {
              // 创建字符输出流对象,关联目的地文件路径
              FileWriter fw = new FileWriter("day10\\hhh\\g.txt");
      
              // 写出数据
              fw.write("看这风景美如画",2,2);
      
              // 关闭流,释放资源
              fw.close();
      
          }
      }
      
      
  • 关闭和刷新

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

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

    • 区别:

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

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

        public class Test {
            public static void main(String[] args) throws Exception{
                // 创建字符输出流对象,关联目的地文件路径
                FileWriter fw = new FileWriter("day10\\hhh\\h.txt");
        
                // 写出数据
                fw.write('刷');
                // 刷新
                fw.flush();
                // 写出数据
                fw.write('新');
                // 刷新
                fw.flush();
        
                // 写出数据
                fw.write("关");
                // 关闭
                fw.close();
        
                // 写出数据
                // fw.write("闭");// 报IOException异常
                // 关闭
                // 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();
    }

  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值