序列化流

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

反之,该字节序列还可以从文件读取出来,重构对象,对它进行反序列化。对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。

ObjectOutputStream类

java.io.ObjectOutputStream类,将Java对象的原始数据类型写入到文件中,实现对象的持久化存储。

构造方法
  • public ObjectOutputStream(OutputStream out):创建一个指定的OutputStream的ObjectOutputStream类对象
特有的独有方法:
  • void writeObject(Object obj):将指定的对象写入到ObjectOutputStream类对象中。
序列化操作
  1. ​ 一个对象想要能够序列化和反序列化,必须满足两个条件:

    • 该类必须实现java.io.Serializable接口,Serializable接口,是一个标记型接口,如果该类没有实现Serializable接口,将会抛出NotSerializableException。

    • 该类的所有属性必须是可以实现序列化或者反序列化。如果有一个属性不想让它参与序列化,则该属性必须标明是瞬态的,瞬时的,这个关键字是transient

public class Student implements Serializable {

    private String name;
private transient Integer age;// 不让age属性参与序列化 }

ObjectInputStream类

java.io.ObjectInputStream类是反序列化流,将之前使用ObjectOutputStream序列化流的原始数据恢复为对象。

构造方法
  • ​ public ObjectInputStream(InputStream in):创建一个指定的InputStream的对象反序列化流对象。
特有的方法:
  • ​ public final Object readObject():从反序列化流中读取一个对象。

对于JVM来说,能够进行反序列的对象 ,前提条件是必须能够找到class文件的类,如果找不到该类的class文件,则会抛出一个ClassNotFoundException异常。

另外,当JVM序列化对象时,能够找到class文件,但是class文件在序列化对象时,发生了修改,那么反序列化操做会抛出一个InvalidClassException异常。原因如下:

  • 该类的序列化版本号与从流中读取出来描述该类的版本号不一致。

  • 该类包含了未知数据类型。

  • 该类没有可访问的无参构造方法。

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

代码演示:

// 序列化操作类
public class Demo01ObjectOutputStream {
public static void main(String[] args) throws IOException {
//1.创建ObjectOutputStream流对象,构造方法中传递指定的字节输出流。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day30_IO\\student.txt"));
//2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中。
//2.1 先创建一个对象
Student s = new Student("小孙", 30);
s.score = 60;
//2.2写对象到文件中
oos.writeObject(s);
//3.释放资源。
oos.close();
}
}
// 反序列化类操作
public class Demo02ObjectInputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 1. 创建一个ObjectInputStream流对象,构造方法中传递一个字节输入流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day30_IO\\student.txt"));
// 2. 使用ObjectInputStream流对象中的方法readObject,读取保存在文件中的对象数据
Object obj = ois.readObject();
// 3.释放资源。
ois.close();
// 4. 查看对象的数据
System.out.println(obj);// Student{name='小孙', age=30}
if ( obj instanceof Student) {
Student student = (Student)obj;
System.out.println(student.getAge() + "--" + student.getName());
} else {
System.out.println("转换失败");
}
}
}
// 需要被序列化的类
import java.io.Serializable;
public class Student implements Serializable {
// 可以选择手动自定义一个序列化版本号
private static final long serialVersionUID = 1L;
//private static String name;
private String name;
private Integer age;
private transient String address = "郑州市";
transient int score;// 0
}

原理分析:

练习:存储一堆对象,实现序列化和反序列化动作。
import java.io.Serializable;

public class Student implements Serializable {
// 可以选择手动自定义一个序列化版本号
private static final long serialVersionUID = 1L;
//private static String name;
private String name;
private Integer age;
private transient String address = "郑州市";
transient int score;// 0
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
address = "郑州市";
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", score=" + score +
'}';
}
} @SuppressWarnings("unchecked")
public class DemoTestSerialize {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.定义多个对象,存储在集合中
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("小孙",30));
list.add(new Student("小王",20));
list.add(new Student("小赵",40));
list.add(new Student("小刘",10));
list.add(new Student("小丽",25));
//2.使用序列化技术,把该集合对象写入到文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day30_IO\\student.txt"));
//3.写入进去,调用writeObject
oos.writeObject(list);
//4.使用反序列化技术,把文件中保存的集合对象读取出来
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day3_IO\\student.txt"));
//5.读取对象数据,调用readObject()方法
Object obj = ois.readObject();
//6.向下转型
if (obj instanceof ArrayList){
ArrayList<Student> students = (ArrayList<Student>)obj;
//7.遍历该集合对象
for (Object student:students){
System.out.println(student);
}
}
}
}

打印流

java.io.PrintStream类能够很方便打印各种数据类型的值。

构造方法
  • public PrintStream(String filename):使用指定的文件名创建一个新的打印流对象。
改变打印流的方向

正常System.out就是PrintStream类型的,数据的流动的位置在控制台中。改变数据的流动位置。通过System.setOut(PrintStream print)来改变流向。

 PrintStream out = System.out;
out.print(123);// 在控制台中
// 构造方法创建一个打印流对象
PrintStream printStream = new PrintStream("day30_IO\\print.txt");
// 改变打印流的方向为"day30_IO\\print.txt"路径
System.setOut(printStream);
System.out.println("我已经改变了输出数据的位置");
System.out.println("我想在控制台中输出数据");
System.out.println("啦啦啦啦啦");

IO流(03)--序列化流、打印流的更多相关文章

  1. java IO之 序列流 集合对象Properties 打印流 流对象

    序列流 也称为合并流. SequenceInputStream 序列流,对多个流进行合并. SequenceInputStream 表示其他输入流的逻辑串联.它从输入流的有序集合开始,并从 第一个输入 ...

  2. Java:IO流其他类(字节数组流、字符数组流、数据流、打印流、Properities、对象流、管道流、随机访问、序列流、字符串读写流)

    一.字节数组流: 类 ByteArrayInputStream:在构造函数的时候,需要接受数据源,而且数据源是一个字节数组. 包含一个内部缓冲区,该缓冲区包含从流中读取的字节.内部计数器跟踪 read ...

  3. Java基础知识强化之IO流笔记60:打印流 之 改进复制文本文件的案例

    1. 使用打印流改进复制文本文件的案例 2. 代码示例: package cn.itcast_03; import java.io.BufferedReader; import java.io.Buf ...

  4. Java基础知识强化之IO流笔记59:打印流

    1. 打印流 (1)分类: • 字节打印流   PrintStream • 字符打印流   PrintWriter (2)打印流的特点: • 只能写数据,不能读数据 • 只能操作目的地,不能操作数据源 ...

  5. JAVA学习第五十四课 — IO流(八)打印流 &amp; 序列流

    一.综合练习-文件清单列表 获取指定文件夹下,指定扩展名的文件(含子文件夹),并将这些文件的绝对路径写到一个文本文件里.也就是建立一个指定扩展名的文件列表 1.深度遍历 2.过滤器->容器 3. ...

  6. File类与常用IO流第十一章——打印流

    第十一章.打印流 概述:java.io.PrintStream extends OutputStream,为其他输出流添加了功能,使题目能够方便的打印各种数据值表示形式. 特点: 只负责数据的输出,不 ...

  7. 零基础学习java------day17------缓冲字节流,转换字节流,简化流,缓冲字符流,序列化和对象流

    1. 缓冲字节流 缓冲区:缓冲区实质上是一个数组.通常它是一个字节数组,但是也可以使用其他种类的数组.但是一个缓冲区不 仅仅 是一个数组.缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程 ...

  8. IO流_PrintWriter(字符打印流)与PrintStream(字节打印流)

    PrintStream:  1.提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式  2.它不抛IOException  3.构造函数接受三种类型的值:  字符串路径  File对象   ...

  9. Java API —— IO流(数据操作流 & 内存操作流 & 打印流 & 标准输入输出流 & 随机访问流 & 合并流 & 序列化流 & Properties & NIO)

    1.操作基本数据类型的流     1) 操作基本数据类型 · DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型.应用程序可以使用数据输出 ...

随机推荐

  1. springboot中aop的使用

    Spring AOP(Aspect Oriented Programming),即面向切面编程,是OOP(Object Oriented Programming,面向对象编程)的补充和完善. OOP引 ...

  2. 这可能是项目中最实用的java8示例了,还不来看?

    ​一.组成及特点 数据源.中间操作.终端操作 流只能使用一次 并行流 和 串行流 二.可以产生流的数据源 集合.文件 三.中间操作 字符串操作拼接joining(""),底层实现是 ...

  3. 对于MySQL数据库四种隔离等级

    对于MySQL事务有四种隔离级别,分别是以下四种: 1.读未提交 2.读提交 3.可重复读 4.串行化(加锁) 对于隔离我们都是说在并发的情况下发生的事情,读取的数据在并发的情况下会发生什么情况. 并 ...

  4. python字节自适应转化单位KB、MB、GB

    文件存储或者传输的过程中,经常需要展示传输文件的大小,或者传输量的大小,为了方便给人展示和阅读,编写一个简单的单位转换器. 1 def hum_convert(value): 2 units = [& ...

  5. HEXO & CARDS主题进阶配置

    我想对于建立一个网站而言,第一步要能够做到正常在线访问以及定期产出一定的内容, 其实当网站建立好那一刻,这第一步已经算是完成了,不过我在此基础之上做了些扩展 在默认的card主题之上,我设置了标签.分 ...

  6. moviepy音视频开发:音频合成类CompositeAudioClip介绍

    ☞ ░ 前往老猿Python博文目录 ░ CompositeAudioClip是AudioClip的直接子类,用于将几个音频剪辑合成为一个音频剪辑.CompositeAudioClip类只有一个构造方 ...

  7. moviepy音视频剪辑VideoClip类fl_image方法及参数image_func的功能介绍

    ☞ ░ 前往老猿Python博文目录 ░ moviepy音视频剪辑模块的视频剪辑基类VideoClip的fl_image方法用于进行对剪辑帧数据进行变换. 调用语法:fl_image(self, im ...

  8. Python中容器指的是什么?

    容器:容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中. 容器是一种可以包含其他类型对象(如列表.元组.字典等)作为元 ...

  9. PyQt(Python+Qt)学习随笔:QLineEdit行编辑器功能详解

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 QLineEdit部件是一个单行文本编辑器,支持撤消和重做. ...

  10. 第11.5节 Python正则表达式搜索任意字符匹配及元字符“.”(点)功能介绍

    在re模块中,任意字符匹配使用"."(点)来表示, 在默认模式下,点匹配除了换行的任意字符.如果指定了搜索标记re.DOTALL ,它将匹配包括换行符的任意字符.关于搜索标记的含义 ...