欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

缓冲流、转换流、序列化流

程序员文章站 2024-03-07 08:05:56
...

目录

 

一、缓冲流

1.缓冲流的作用

2.缓冲流的分类

3.字节缓冲流的介绍和使用

4.字符缓冲流的介绍和使用

5.综合练习:文本排序

二、转换流

1.字符编码

2.字符集

3.编码引出的问题

4.InputStreamReader类

5.OutputStreamWriter类

三、序列化流

1.什么是序列化流

2.ObjectOutputStream类的使用

(1)构造方法

(2)序列化操作的前提

(3)写出对象方法

3.ObjectInputStream类的使用

(1)构造方法

(2)反序列化操作的异常分析

(3)读取对象方法

4.序列化多个对象练习

四、打印流PrintStream

1.介绍

2. 构造方法

3.小练习:改变打印流向


一、缓冲流

1.缓冲流的作用

缓冲流又叫增强流,用来给四大基本流做性能方面的加强。

2.缓冲流的分类

字节缓冲流: BufferedInputStream , BufferedOutputStream

字符缓冲流: BufferedReader , BufferedWriter

3.字节缓冲流的介绍和使用

(1)字节缓冲流的构造

public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。

public BufferedOutputStream(OutputStream out) : 创建一个新的缓冲输出流。

4.字符缓冲流的介绍和使用

(1)字符缓冲流的构造

public BufferedReader(Reader in) :创建一个 新的缓冲输入流。

public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。

(2)特有方法

BufferedReader: public String readLine() : 读一行文字。

BufferedWriter: public void newLine() : 写一行行分隔符,由系统属性定义符号。

5.综合练习:文本排序

缓冲流、转换流、序列化流

HashMap<String, String> linemap = new HashMap<>();
        //创建流对象
        try (BufferedReader br = new BufferedReader(new FileReader("出师表"));
             BufferedWriter bw = new BufferedWriter(new FileWriter("出师表02.txt"));) {
            String line = null;
            //读取数据
            while ((line = br.readLine()) != null) {
                //解析文本
                String[] split = line.split("\\.");
                //保存到集合
                linemap.put(split[0], split[1]);
            }
            //遍历集合
            for (int i = 1; i <= linemap.size(); i++) {
                //获取map中文本
                String value = linemap.get(String.valueOf(i));
                //写出拼接文本
                bw.write(i + "." + value);
                //换行
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

二、转换流

1.字符编码

就是一套自然语言的字符与二进制数之间的对应规则。

编码:字符通过编码转成对应的码值(看的懂的变为看不懂的)

解码:码值通过解码转成对应的字符(看不懂的变为看的懂的)

2.字符集

是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

缓冲流、转换流、序列化流

3.编码引出的问题

在IDEA中,使用FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8 编码,所以没有任何问题。但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。

4.InputStreamReader类

转换流java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁。

(1)构造方法

InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。

InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流。

5.OutputStreamWriter类

转换流java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。

(1)构造方法

OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流。

OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流。

三、序列化流

1.什么是序列化流

Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的数据等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

2.ObjectOutputStream类的使用

(1)构造方法

public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream。

(2)序列化操作的前提

一个对象要想序列化,必须满足两个条件:

①该类必须实现java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException 。

②该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。

(3)写出对象方法

public final void writeObject (Object obj) : 将指定的对象写出。

3.ObjectInputStream类的使用

(1)构造方法

public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream。

(2)反序列化操作的异常分析

①InvalidClassException异常

当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException 异常。发生这个异常的原因如下:

A.该类的序列版本号与从流中读取的类描述符的版本号不匹配

B.该类包含未知数据类型

C.该类没有可访问的无参数构造方法

Serializable 接口给需要序列化的类,提供了一个序列版本号。serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

②ClassNotFoundException异常

序列化前后,被序列化类被删除了。

(3)读取对象方法

public final Object readObject () : 读取一个对象。

4.序列化多个对象练习

分析:

(1)把若干学习对象 ,保存到集合中。

(2)把集合序列化。

(3)反序列化读取时,只需要读取一次,转换为集合类型。

(4)遍历集合,可以打印所有的学生信息

代码如下:

public class Student implements Serializable {
    private static final long serialVersionUID = 8002194731998770433L;
    private String name;
    private int age;

    public Student() {
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
 public static void main(String[] args) throws Exception {
        // 创建 学生对象
        Student student = new Student("老王", 20);
        Student student2 = new Student("老张", 22);
        Student student3 = new Student("老李", 24);
        ArrayList<Student> arrayList = new ArrayList<>();
        arrayList.add(student);
        arrayList.add(student2);
        arrayList.add(student3);
        // 序列化操作
        serializ(arrayList);
        // 反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.txt"));
        // 读取对象,强转为ArrayList类型
        ArrayList<Student> list = (ArrayList<Student>) ois.readObject();
        for (int i = 0; i < list.size(); i++) {
            Student s = list.get(i);
            System.out.println(s.getName() + "‐‐" + s.getAge());
        }
    }

    private static void serializ(ArrayList<Student> arrayList) throws Exception {
        // 创建 序列化流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));
        // 写出对象
        oos.writeObject(arrayList);
        // 释放资源
        oos.close();
    }

四、打印流PrintStream

1.介绍

作用:用来打印各种数据类型

特点:

         a.永远不会抛出IOException

         b.不需要关心字符字节,打印什么就是什么

2. 构造方法

public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流。

PrintStream(OutputStream out): 创建一个新的打印流。

PrintStream(File file): 使用指定的文件创建一个新的打印流。

3.小练习:改变打印流向

 // 调用系统的打印流,控制台直接输出97
        System.out.println(97);
        // 创建打印流,指定文件的名称
        PrintStream ps = new PrintStream("ps.txt");
        // 设置系统的打印流流向,输出到ps.txt
        System.setOut(ps);
        // 调用系统的打印流,ps.txt中输出97
        System.out.println(97);