java 的 对象流,打印流,转换流:ObjectOutputStream、PrintStream、InputStream、InputStreamReader等

1 序列化和反序列化

有如下需求:

  1. int num = 100,这个数据保存到文件中,需要同时保存数据类型 int,并且还需要能够从文件中直接恢复为 int 100

  2. Dog dog = new Dog("小黄", 3) 这个 dog 对象保存到文件中,并且能够从文件中恢复。

完成如上的要求,我们可以使用序列化的特性。

序列化和反序列化

序列化:就是在保存数据的时,保存数据的值和数据类型

反序列化:就是在恢复数据时,恢复数据的值和数据类型

注意: 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的该类必须实现如下2个接口之一:

  • Serializable:这是一个标记接口,没有方法
  • Externalizable:该接口有方法需要实现,因此在使用时,一般使用 Serializable 接口

2 对象流

对象流: 提供了对基本数据类型或对象类型的序列化和反序列化的方法

ObjectOutputStream 提供 序列化功能

ObjectInputStream 提供 反序列化功能

2.1 ObjectOutputStream 介绍

ObjectOutputStream 类的继承、实现关系如下图:

案例讲解: 使用 ObjectOutputStream 序列化基本数据类型和一个 Dog 对象,并保存到 data.dat 文件中。

import java.io.*;

public class ObjectOutput1_ {
    public static void main(String[] args) throws IOException {
		//序列化后,保存的文件格式,不是纯文本
        //而是按照指定格式要求 .dat
        ObjectOutputStream objectInputStream = new ObjectOutputStream(new FileOutputStream("d:\\0\\data.dat"));
        //int->Integer (实现了 Serializable)
        objectInputStream.writeInt(3);
        //boolean-> Boolean (实现了 Serializable)
        objectInputStream.writeBoolean(true);
        // char-> Character (实现了 Serializable)
        objectInputStream.writeChar('a');
        //double-> Double (实现了 Serializable)
        objectInputStream.writeDouble(22.4);
        objectInputStream.writeObject(new Dog());

        objectInputStream.close();
    }
}

class Dog implements Serializable{

}

2.2 ObjectInputStream 的介绍

ObjectInputStream 类的继承、实现关系如下图:

案例讲解: 使用 ObjectInputStream 读取 data.dat 并反序列化恢复数据。

注意: data.dat 中的数据在反序列化时,需要按照当初序列化的数据的顺序进行,不然反序列化将会失败。

package object_;

import java.io.*;

public class ObjectInput1_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("d:\\0\\data.dat"));
		//注意顺序
        System.out.println(inputStream.readInt());
        System.out.println(inputStream.readBoolean());
        System.out.println(inputStream.readChar());
        System.out.println(inputStream.readDouble());
        System.out.println(inputStream.readObject());

        inputStream.close();
    }
}

2.3 对象流的注意事项

  1. 读写顺序要一致,即元素序列化的顺序,要和反序列化的顺序一致。
  2. 要求序列化或反序列化对象,则该对象的类需要实现 Serializable 。
  3. 序列化的类中建议添加 SerialVersionUID,为了提高版本的兼容性。
  4. 序列化对象时,默认将里面所有属性都进行序列化,但除了 static 或 transient 修饰的成员
  5. 序列化对象时,要求里面的属性类型也需要实现序列化接口
  6. 序列化具备可继承性,也就是如果某类实现了序列化,则它的所有子类也已经默认实现了序列化。

3 标准输入输出流

类型用途常见包装类
System.inInputStream读取输入(如键盘)Scanner, BufferedReader
System.outPrintStream输出正常信息(控制台)直接使用
System.errPrintStream输出错误信息直接使用

正如我们平常使用的一样:

Scanner in = new Scanner(System.in);

System.out.println();

4 转换流

转换流: InputStreamReaderOutputStreamWriter

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

InputStreamReader 的构造方法:

image-20250406210111956

OutputStreamWriter 的构造方法:

image-20250406210159318

由上可以看出,这2个类的构造方法,都存在支持指定编码方式的重载。

案例讲解: 使用 InputStreamReader 进行输入,并指定编码方式。

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

public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        //1.创建FileInputStream对象
//        FileInputStream fileInputStream = new FileInputStream("d:\\0\\second.txt");
        //2.创建InputStreamReadre对象,并指定编码方式
//        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "gbk");
		//3.创建BufferedReader对象进行输入
        //BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        //将前面所有步骤合在一起
        BufferedReader br = new BufferedReader(new InputStreamReader((new FileInputStream                                                     ("d:\\0\\second.txt")), "gbk"));
        String s = br.readLine();
        System.out.println(s);
        
        br.close();
    }
}

5 打印流

打印流: PrintStream 和 PrintWriter

注意: 打印流只有输出流,没有输入流

案例演示: 使用 PrintWriter 进行打印输出。

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintWriter_ {
    public static void main(String[] args) throws IOException {
        //输出到控制台
        PrintWriter printWriter = new PrintWriter(System.out);
        //输出到文件 second.txt
        PrintWriter printWriter1 = new PrintWriter(new FileWriter("d:\\0\\second.txt"));

        printWriter.write('a');//输出到控制台
        printWriter1.write(8);//输出到second.txt文件里

        printWriter.close();
        printWriter1.close();
    }
}

案例演示: 使用PrintStream 进行打印输出。

import java.io.FileNotFoundException;
import java.io.PrintStream;

public class PrintStream_ {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream printStream = System.out;

        printStream.print(6);
        //因为print 底层使用的是write,
        // 所以我们可以直接调用write进行打印/输出
        printStream.write('9');

        //我们可以去修改打印流输出的位置/设备
        //1. 输出修改成到 "d:\\0\\second.txt"
        //2. "6" 和 "9" 就会输出到 "d:\\0\\second.txt"

        //3. public static void setOut(PrintStream out) {
        //      checkIO();
        //      setOut0(out); // native 方法,修改了 out
        // }
        //使用SetOut() 方法
        System.setOut(new PrintStream("d:\\0\\second.txt"));
        System.out.println('t');

        printStream.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值