非零基础自学Java (老师:韩顺平)

✈【【零基础 快速学Java】韩顺平 零基础30天学会Java】

第19章 IO流


文章目录

  • 非零基础自学Java (老师:韩顺平)
  • 第19章 IO流
  • 19.5 节点流 和 处理流
  • 19.5.1 基本介绍
  • 19.5.2 节点流 和 处理流 一览图
  • 19.5.3 节点流 和 处理流 的区别和联系
  • 19.5.4 处理流的主要功能体现
  • 19.5.5 处理流 - BufferedReader 和 BufferedWriter
  • 19.5.6 处理流 - BufferedInputStream 和 BufferedOutputStream
  • 19.5.7 介绍BufferedOutputStream
  • 19.5.8 对象流 - ObjectInputStream 和 ObjectOutputStream
  • 19.5.9 对象流介绍
  • 19.5.10 标准输入输出流
  • 19.5.11 转换流 - InputStreamReader 和 OutputStreamWriter


19.5 节点流 和 处理流
19.5.1 基本介绍
  • 节点流 可以从一个特定的数据源读写数据。如FileReader、FileWriter
  • 处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferedReader、BufferedWriter
19.5.2 节点流 和 处理流 一览图

韩顺平java笔记下载 韩顺平java百度网盘_java

19.5.3 节点流 和 处理流 的区别和联系
  • 节点流是底层流/低级流,直接跟数据源相接。
  • 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
  • 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
19.5.4 处理流的主要功能体现
  • 性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
  • 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
19.5.5 处理流 - BufferedReader 和 BufferedWriter

BufferedReader 和 BufferedWriter属于字符流,是按照字符来读取数据的关闭时处理流,只需要关闭外层流即可

【举个栗子】

使用BufferedReader读取文本文件,并显示在控制台

package com.dingjiaxiong.reader_;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * ClassName: BufferedReader_
 * date: 2022/9/7 13:36
 *
 * @author DingJiaxiong
 */

public class BufferedReader_ {
    public static void main(String[] args) throws Exception {
        String filePath = "F:\\IO流学习\\poem.txt";

        //创建bufferedReader
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));

        //读取
        String line; //按行读取
        //1. bufferedReader.readLine() 是按行读取文件
        //2. 当返回 null 时,表示文件读取完毕
        while ((line = bufferedReader.readLine()) != null){
            System.out.println(line);
        }

        //关闭流
//        只需要关闭 BufferedReader ,因为底层会自动的去关闭 节点流
        bufferedReader.close();
    }
}

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_韩顺平java笔记下载_02

【再一个栗子,使用BufferedWriter 将”韩老师666”,写入到文件中】

package com.dingjiaxiong.writer_;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/**
 * ClassName: BufferedWriter_
 * date: 2022/9/7 13:41
 *
 * @author DingJiaxiong
 */

public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath = "F:\\IO流学习\\ok.txt";

        //创建BufferedWriter
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));

        bufferedWriter.write("韩老师666");

        bufferedWriter.newLine(); //插入一个和系统相关的 换行

        bufferedWriter.write("韩老师666222222");

        bufferedWriter.newLine();

        bufferedWriter.write("韩老师666666333333333");

        bufferedWriter.newLine();

        //关闭外层流即可
        bufferedWriter.close();
    }
}

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_序列化_03

【综合使用BufferedReader 和 BufferedWriter 完成文本文件拷贝】

package com.dingjiaxiong.writer_;


import java.io.*;

/**
 * ClassName: BufferedCopy_
 * date: 2022/9/7 13:45
 *
 * @author DingJiaxiong
 */

public class BufferedCopy_ {
    public static void main(String[] args) {
        //1. BufferedReader 和 BufferedWriter 是安装字符操作
        //2. 不要去操作 二进制文件[声音,视频,doc, pdf ], 可能造成文件损坏

        String srcFilePath = "F:\\IO流学习\\poem.txt";
        String destFilePath = "D:\\poem_copy.txt";

        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        
        String line;

        try {
            bufferedReader = new BufferedReader(new FileReader(srcFilePath));
            bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));

            while ((line = bufferedReader.readLine()) != null){
                bufferedWriter.write(line);
                //插入一个换行
                bufferedWriter.newLine();
            }
            System.out.println("拷贝完毕");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭流
            try {
                if (bufferedReader != null){
                    bufferedReader.close();
                }
                if (bufferedWriter != null){
                    bufferedWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_韩顺平java笔记下载_04

19.5.6 处理流 - BufferedInputStream 和 BufferedOutputStream

【BufferedInputStream】

韩顺平java笔记下载 韩顺平java百度网盘_servlet_05

BufferedlnputStream是字节流,在创建BufferedlnputStream时,会创建一个内部缓冲区数组.

韩顺平java笔记下载 韩顺平java百度网盘_java_06

19.5.7 介绍BufferedOutputStream

韩顺平java笔记下载 韩顺平java百度网盘_servlet_07

BufferedOutputStream是字书流

实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统

韩顺平java笔记下载 韩顺平java百度网盘_序列化_08

【举个栗子】

完成图片拷贝

package com.dingjiaxiong.outputstream_;

import java.io.*;

/**
 * ClassName: BufferedCopy02
 * date: 2022/9/7 13:56
 *
 * @author DingJiaxiong
 */

public class BufferedCopy02 {
    public static void main(String[] args) throws IOException {

        String srcFilePath = "F:\\test.jpg";
        String destFilePath = "E:\\test_copy.jpg";

        //创建 BufferedOutputStream 对象、BufferedInputStream 对象
        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;

        try {
            bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFilePath));
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));

            //循环读取文件,并写入到 destFilePath
            byte[] buff = new byte[1024];

            int readLen = 0;

            //返回-1,则表示文件读取完毕
            while ((readLen = bufferedInputStream.read(buff)) != -1){
                bufferedOutputStream.write(buff , 0 , readLen);
            }

            System.out.println("文件拷贝完毕");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (bufferedInputStream != null){
                bufferedInputStream.close();
            }
            if (bufferedOutputStream != null){
                bufferedOutputStream.close();
            }
        }

    }
}

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_java_09

19.5.8 对象流 - ObjectInputStream 和 ObjectOutputStream

【序列化 和 反序列化】

  • 序列化就是在保存数据时,保存数据的值和数据类型
  • 反序列化就是在恢复数据时,恢复数据的值和数据类型
  • 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
    Serializable //这是一个标记接口,没有方法
    Externalizable //该接口有方法需要实现,因此一般实现上面的Serializable接口

韩顺平java笔记下载 韩顺平java百度网盘_韩顺平java笔记下载_10

19.5.9 对象流介绍

功能:提供了对基本类型或对象类型的序列化和反序列化的方法

  • ObjectOutputStream 提供 序列化功能
  • ObjectInputStream 提供 反序列化功能

韩顺平java笔记下载 韩顺平java百度网盘_jvm_11

【举个栗子】

使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name, age),并保存到data.dat文件中

package com.dingjiaxiong.outputstream_;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * ClassName: ObjectOutStream_
 * date: 2022/9/7 14:10
 *
 * @author DingJiaxiong
 */

public class ObjectOutStream_ {
    public static void main(String[] args) throws Exception {
        序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
        String filePath = "E:\\data.dat";

        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));

        //序列化数据到 data.txt
        objectOutputStream.writeInt(100);  // int → Integer( 实现了Serializable
        objectOutputStream.writeBoolean(true); // boolean → Boollean ( 实现了Serializable
        objectOutputStream.writeChar('a'); //char → Character ( 实现了Serializable
        objectOutputStream.writeDouble(9.5); // double → Double ( 实现了Serializable
        objectOutputStream.writeUTF("韩老师666"); //String

        //保存一个dog 对象
        objectOutputStream.writeObject(new Dog("旺财",10));
        objectOutputStream.close();

        System.out.println("数据保存完毕(序列化形式)");
    }
}

class Dog implements Serializable{
    private String name;
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_java_12

【使用ObjectInputStream 读取data.dat 并反序列化恢复数据】

System.out.println("==========反序列化=============");

//进行反序列化
//创建流对象
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("E:\\data.dat"));

//读入,注意顺序
System.out.println(objectInputStream.readInt());
System.out.println(objectInputStream.readBoolean());
System.out.println(objectInputStream.readChar());
System.out.println(objectInputStream.readDouble());
System.out.println(objectInputStream.readUTF());
System.out.println(objectInputStream.readObject());

//关闭
objectInputStream.close();
System.out.println("以反序列化的方式读取(恢复) OK");

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_servlet_13

【注意事项】

  • 读写顺序要一致
  • 要求序列化或反序列化对象,需要实现 Serializable
  • 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
  • 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
  • 序列化对象时,要求里面属性的类型也需要实现序列化接口
  • 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
19.5.10 标准输入输出流

类型

默认设备

System.in 标准输入

InputStream

键盘

System.out 标准输出

PrintStream

显示器

【举个栗子】

传统方法System.out.printIn(“”); 就是使用out对象将数据输出到显示器

传统的方法, Scanner是从标准输入键盘接收数据

19.5.11 转换流 - InputStreamReader 和 OutputStreamWriter

【举个栗子,看一个文件乱码问题】

韩顺平java笔记下载 韩顺平java百度网盘_java_14

韩顺平java笔记下载 韩顺平java百度网盘_序列化_15

package com.dingjiaxiong.transformation;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * ClassName: CodeQuestion
 * date: 2022/9/7 14:36
 *
 * @author DingJiaxiong
 */

public class CodeQuestion {
    public static void main(String[] args) throws IOException {
        String filePath = "E:\\test.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));

        String s = bufferedReader.readLine();

        //默认UTF - 8 ,如果文件不是 UTF - 8 编码

        System.out.println("读取到的内容:" + s);
        bufferedReader.close();
    }
}

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_java_16

【基本介绍】

  • InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流)
  • OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
  • 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
  • 可以在使用时指定编码格式(比如utf-8, gbk , gb2312, ISO8859-1等)

【举个栗子】

将字节流 FileInputStream 转成字符流 InputStreamReader, 指定编码 gbk/utf-8

package com.dingjiaxiong.transformation;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * ClassName: InputStreamReader_
 * date: 2022/9/7 14:43
 *
 * @author DingJiaxiong
 */

public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {

        String filePath = "E:\\test.txt";

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gbk"));

        //读取
        String s = bufferedReader.readLine();
        System.out.println("读取内容 = " + s);

        //关闭外层流
        bufferedReader.close();

    }
}

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_servlet_17

【再举个栗子】

编程将字节流 FileOutputStream包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式,可以指定其他,比如utf-8)

OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("d:\\testtest.txt"),"gbk");

//写入
outputStreamWriter.write("韩老师666");

//关闭
outputStreamWriter.close();
System.out.println("保存成功");

运行结果

韩顺平java笔记下载 韩顺平java百度网盘_韩顺平java笔记下载_18