019.day19 缓冲流 对象流 标准输入输出流

目录

缓冲流和对象流

本节任务

缓冲流

对象流

标准输入输出流

教学目标

掌握缓冲流的用法

掌握序列化和反序列化

掌握标准输入输出流的用法

教学内容

一、缓冲流

主要为了提高读写效率,增强基础流的功能

  • 实例化File对象
  • 实例化缓冲流对象,需要基础流作为参数

    1. 缓冲输入流

    (1)BufferedInputStream
// TODO 字符缓冲输入流BufferedReader
        // 1.实例化一个BufferedReader
        // 默认缓冲区大小:8192,当标记中指定的记录的字符数小于缓冲数组剩余长度时,不会发生异常
        // 当缓冲数组足够大时,该标记一直会保留到当前缓冲数组装满
        Reader reader = new BufferedReader(new FileReader(new File("f:/test.txt")),5);
        // 2.BufferedReader中支持mark和reset
        String result = "";
        // 3.使用mark进行标记
        result += (char)reader.read();
        result += (char)reader.read();
        result += (char)reader.read();
        result += (char)reader.read();
        // mark当中参数的作用:再读取多少个字符之后,标记点失效
        reader.mark(3);
        // 4.使用reset方法返回标记的位置
        result += (char)reader.read();
        result += (char)reader.read();
        result += (char)reader.read();
        // 失效:limit -> 要求记录的字符数 -> 失效条件:读取的字符总数会超出缓冲区大小
        // 当需要记录的字符刚好超出了当前缓冲区,会在下一个缓冲区中继续存放,直到下一个缓冲区存满,标记失效
        reader.reset();
        result += (char)reader.read();
        result += (char)reader.read();
        result += (char)reader.read();
        System.out.println(result);
        reader.close();
  • mark(int marklimit):标记位置
  • reset():如果可能,回到标记位置
// TODO 缓冲流-标记和重置练习
        // 在文本文件中指定一对特殊字符(能够被唯一识别的)
        // 当读取到第一个特殊字符时,标记当前位置
        // 当读取到第二个特殊字符时,重置,继续读取完所有文件内容
        Reader reader = new BufferedReader(new FileReader(new File("f:/test.txt")));
        int i = 0;
        int count = 1;
        String result = "";
        while ((i = reader.read()) != -1) {
            if ('!' == (char)i && count == 1) {
                reader.mark(30);
                count ++;
            }else if('!' == (char)i && count == 2) {
                reader.reset();
                count ++;
            }
            result += (char)i;
        }
        System.out.println(result);
        reader.close();
(2)BufferedReader
  • readLine():直接读取一行
// TODO 字符缓冲流 - 每次读取一行 - 读取文件中所有内容
        // 1.初始化缓冲流
        BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("E:/test.txt")));
        String line = "";
        // 2.读取文件内容
        while ((line = bufferedReader.readLine()) != null) {
            // 读取的内容本身不包括换行符
            System.out.println(line);
        }
        // 3.关闭流
        bufferedReader.close();
  • 小练习

    // TODO 从文件中读取所有数据 - 单词计数
          // 1.数据采集 - 数据来源:文本文件
          // (1)指定文件路径
          // 使用File类指定数据文件路径
          File dataFile = new File("E:/data.txt");
          // 使用dataFile初始化一个输入流
          Reader fileReader = new FileReader(dataFile);
          // 使用fileReader初始化一个缓冲流
          BufferedReader bufferedReader = new BufferedReader(fileReader);
          // (2)使用缓冲流一次读取一行
          // 定义一个集合,存储读取到的数据
          List<String> lines = new ArrayList<>();
          // 定义字符串变量,接收每次读取的一行数据
          String temp = "";
          // (3)将获取到的数据存放到集合当中
          while ((temp = bufferedReader.readLine()) != null) {
              lines.add(temp);
          }
          // (4)关闭流 -> 关闭顺序与打开顺序相反
          bufferedReader.close();
          fileReader.close();
          // 2.数据清洗 - 去除重复、缺失、偏差较大的数据
          // 3.数据分析 - 统计计数
          Map<String, Integer> result = new HashMap<>();
          // (1)从集合中获取到每一行数据
          for (String line : lines) {
              // (2)根据相应的分隔符取出每一个单词作为待统计数据
              String[] words = line.split(" ");
              for (String word : words) {
                  // (3)当某一个单词第一次出现时,记为1
                  // (4)当某一个单词再次出现时,将出现的次数累加
                  // 第一次出现该单词
                  if (!result.containsKey(word)) {
                      result.put(word, 1);
                  }else {
                      // 取出当前单词已经出现的次数
                      int count = result.get(word);
                      result.put(word, count + 1);
                  }
              }
          }
          // (5)重复以上步骤,直到遍历结束
          // 4.结果打印
          for (Map.Entry<String, Integer> string : result.entrySet()) {
              System.out.println(string);
          }

2. 缓冲输出流

(1)BufferedOutputStream
(2)BufferedWriter
  • newLine():写入一个行分隔符

    二、对象流

    如果流中流动的数据是对象则可称为对象流

  • 序列化:将一个对象写入到本地文件中
  • 反序列化:将一个本地文本文件中的对象读取出来
  • 一个对象流只能操作一个对象
  • 当需要同时序列化多个对象时,可以使用集合
// TODO 对象流
        // 输出流 -> 序列化过程 : 将当前对象当中包含的信息(状态) -> 保存至文件当中
        // 1-1.初始化对象输出流 -> 需要的参数 : 通用的输出流 -> FileOutputStream -> File -> 路径
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("E:/shop.txt")));
        // 输入流 -> 反序列化过程 : 将文件当中存放的对象的信息 -> 返回一个对象(数据)
        // 1-2.初始化对象输入流 -> 需要的参数 : 通用的输入流 -> FileInputStream -> File -> 路径
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("E:/shop.txt")));
        // 2.获得一个自定义类的实例
        Shop shop = new Shop("百货商厦");
        // 3-1.序列化对象 - 自定义类实现序列化接口 - ID根据需要进行生成
        outputStream.writeObject(shop);
        // 3-2.反序列化 - 判断类型 - 强制转换接收
        Object object = inputStream.readObject();
        // 如果反序列化得到的对象是相应的实例
        if (object instanceof Shop) {
            // 检查是否成功反序列化
            Shop newShop = (Shop)object;
            System.out.println(newShop);
        }
        // 4.强制刷新
        outputStream.flush();
        // 5.关闭流
        inputStream.close();
        outputStream.close();
//Product类中有引用数据类型变量Shop
// TODO 对象流应用 - 对象的深度克隆
        // 输出流 -> 序列化过程 : 将当前对象当中包含的信息(状态) -> 保存至文件当中
        // 1-1.初始化对象输出流 -> 需要的参数 : 通用的输出流 -> FileOutputStream -> File -> 路径
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("E:/product.txt")));
        // 输入流 -> 反序列化过程 : 将文件当中存放的对象的信息 -> 返回一个对象(数据)
        // 1-2.初始化对象输入流 -> 需要的参数 : 通用的输入流 -> FileInputStream -> File -> 路径
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("E:/product.txt")));
        // 2.获得一个自定义类的实例
        Product oldProduct = new Product("商品1", 200, new Shop("商店1"));
        // 3-1.序列化对象 - 自定义类实现序列化接口 - ID根据需要进行生成
        outputStream.writeObject(oldProduct);
        // 3-2.反序列化 - 判断类型 - 强制转换接收
        Object object = inputStream.readObject();
        // 如果反序列化得到的对象是相应的实例
        if (object instanceof Product) {
            // 检查是否成功反序列化
            Product newProduct = (Product) object;
            System.out.println(oldProduct);
            System.out.println(newProduct);
            oldProduct.setName("商品11");
            newProduct.setName("商品2");
            newProduct.getShop().setName("商店2");
            System.out.println(oldProduct);
            System.out.println(newProduct);
        }
        // 4.强制刷新
        outputStream.flush();
        // 5.关闭流
        inputStream.close();
        outputStream.close();
public class Product implements Serializable {

    public Product() {
        
    }

    public Product(String name, Integer price) {
        this.name = name;
        this.price = price;
    }
    
    public Product(String name, Integer price, Shop shop) {
        this.name = name;
        this.price = price;
        this.shop = shop;
    }

    private String name;
    // 封装类型比较时注意缓存机制以及手动拆箱
    private Integer price;
    // 成员变量中出现自定义类型,实例是一个引用类型
    private Shop shop;

    public Shop getShop() {
        return shop;
    }

    public void setShop(Shop shop) {
        this.shop = shop;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Product [name=" + name + ", price=" + price + ", shop=" + shop + "]";
    }
public class Shop implements Serializable {
    
    private static final long serialVersionUID = -9099382180185766414L;

    public Shop() {

    }

    public Shop(String name) {
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Shop [name=" + name + "]";
    }
    
}

1. 序列化

  • ObjectOutputStream
  • writeObject(Object obj):将对象写入流中

    2. 反序列化

  • ObjectInputStream
  • readObject():从流中读取对象
// TODO 对象流应用 - 对象的深度克隆
        // 输出流 -> 序列化过程 : 将当前对象当中包含的信息(状态) -> 保存至文件当中
        // 1-1.初始化对象输出流 -> 需要的参数 : 通用的输出流 -> FileOutputStream -> File -> 路径
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("E:/product.txt")));
        // 输入流 -> 反序列化过程 : 将文件当中存放的对象的信息 -> 返回一个对象(数据)
        // 1-2.初始化对象输入流 -> 需要的参数 : 通用的输入流 -> FileInputStream -> File -> 路径
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("E:/product.txt")));
        // 2.获得一个自定义类的实例
        Product oldProduct = new Product("商品1", 200, new Shop("商店1"));
        // 3-1.序列化对象 - 自定义类实现序列化接口 - ID根据需要进行生成
        outputStream.writeObject(oldProduct);
        // 3-2.反序列化 - 判断类型 - 强制转换接收
        Object object = inputStream.readObject();
        // 如果反序列化得到的对象是相应的实例
        if (object instanceof Product) {
            // 检查是否成功反序列化
            Product newProduct = (Product) object;
            System.out.println(oldProduct);
            System.out.println(newProduct);
            oldProduct.setName("商品11");
            newProduct.setName("商品2");
            newProduct.getShop().setName("商店2");
            System.out.println(oldProduct);
            System.out.println(newProduct);
        }
        // 4.强制刷新
        outputStream.flush();
        // 5.关闭流
        inputStream.close();
        outputStream.close();

三、标准输入输出流

标准输入输出流是System.in和System.out,默认情况下代表键盘和显示器

1. 输出流

  • PrintStream
  • setOut(PrintStream out):重新分配标准输出流
// TODO 标准的输出流
        PrintStream out = System.out;
        System.out.println("123");
        OutputStream outputStream = new FileOutputStream("E:/SystemTest.txt");
        // 自定义输出路径 默认屏幕上
        System.setOut(new PrintStream(outputStream));
        System.out.println("456");
        System.setOut(out);
        System.out.println(456);

2. 输入流

  • setIn(InputStream in):重新分配标准输入流
// TODO 标准的输入流
        InputStream in = System.in;
        InputStream inputStream = new FileInputStream(new File("E:/SystemTest.txt"));
        System.setIn(inputStream);
        Scanner scanner = new Scanner(System.in);
        // 使用Scanner实现文件内容读取
        while (scanner.hasNext()) {
            System.out.println(scanner.nextLine());
        }
        System.setIn(in);
        scanner = new Scanner(System.in);
        scanner.nextLine();
        scanner.close();
  • 小练习
// TODO 标准流练习
        // 从键盘录入一组数据(字符串)
        PrintStream out = System.out;
        // (1)使用默认的标准输入流初始化一个Scanner对象
        Scanner scanner = new Scanner(System.in);
        // (2)定义一个集合用于存放接收到的字符串
        List<String> list = new ArrayList<>();
        int n = 4;
        System.out.println("请输入四条数据:");
        for(int i = 0;i < n;i ++) {
            list.add(scanner.nextLine());
        }
        // 使用标准输出流写入到文件中
        // (1)定义一个文件输出流 -> 指定到某一个文件
        OutputStream outputStream = new FileOutputStream(new File("E:/SystemTest.txt"));
        // (2)改变标准输出流的指向 -> 文件输出流
        System.setOut(new PrintStream(outputStream));
        // (3)遍历集合,使用println()方法输出集合元素
        for (String line : list) {
            System.out.println(line);
        }
        // 利用标准输入流实现使用Scanner读取文件中的内容,打印输出
        // (1)定义一个文件输入流 -> 指定到数据记录文件
        InputStream inputStream = new FileInputStream(new File("E:/SystemTest.txt"));
        // (2)改变标准输入流的指向 -> 文件输入流
        System.setIn(inputStream);
        // (3)使用改变后的标准输入流初始化一个新的Scanner对象
        scanner = new Scanner(System.in);
        // (4)重置标准输出流 -> 显示器
        System.setOut(out);
        // (5)使用Scanner对象的nextLine()方法读取数据
        while (scanner.hasNext()) {
            System.out.println(scanner.nextLine());
        }
        scanner.close();

猜你喜欢

转载自www.cnblogs.com/yokii/p/9441913.html