美文网首页
从屌丝到架构师的飞越(IO流篇)-序列化流

从屌丝到架构师的飞越(IO流篇)-序列化流

作者: 走着别浪 | 来源:发表于2019-07-10 07:41 被阅读0次

一.介绍

序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。    对象 -- 流数据(ObjectOutputStream)

反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream)

序列化流和反序列化流不同于字节流、字符流、内存字节流,这些都是把字符串写入/读取文件,序列化流和反序列化流可以将对象写入/读取文本文件中.

但是我们要注意的是,写入和读取的文件要实现Serializable这个接口,当然这个接口是没有任何方法的,直接implements就好,类似于这种没有任何方法的接口被称为标记接口.

二.知识点介绍

1、概念

2、序列化

3、序列化流

4、对象反序列化流

5、将用户信息存储到文件中与读取文件用户

6、序列化接口

7、瞬态关键字transient

三.上课视频对应说明文档

1、序列化流概念

序列化流可以将对象进行序列化和反序列化。

用于从流中读取对象的操作流 ObjectInputStream称为反序列化流

用于向流中写入对象的操作流 ObjectOutputStream称为序列化流

注意:对象序列化时,对象的数据类型定义时一定要实现Serializable接口,从而实现可持久化。

2、序列化

对象的寿命通常随着生成该对象的程序的终止而终止,有时候需要把在内存中的各种对象的状态(也就是实例变量,不是方法)保存下来,并且可以在需要时再将对象恢复。虽然你可以用你自己的各种各样的方法来保存对象的状态,但是Java给你提供一种应该比你自己的好的保存对象状态的机制,那就是序列化。

总结:Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里(系列化),并且可以从其它地方把该Byte 流里的数据读出来(反序列化)。

2.1、序列化的用途

(1)想把的内存中的对象状态保存到一个文件中或者数据库中时候

(2)想把对象通过网络进行传播的时候

2.2、序列化的实现

实现Serializable接口

3、序列化流

将一个对象以对象的形式存储到文件中。

ObjectOutputStream writeObject():写出对象

代码示例:

public class ObjectStreamDemo {

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

/*

* 将一个对象存储到持久化(硬盘)的设备上。

*/

writeObj();//对象的序列化。

}

public static void writeObj() throws IOException {

//1,明确存储对象的文件。

FileOutputStream fos = new FileOutputStream("aa\\obj.txt");

//2,给操作文件对象加入写入对象功能。

ObjectOutputStream oos = new ObjectOutputStream(fos);

//3,调用了写入对象的方法。

oos.writeObject(new Person("wangcai",20));

//关闭资源。

oos.close();

}

}

4、对象反序列化流

当把一个对象持久化存储起来之后,需要使用反序列化技术获取存储起来的对象

ObjectInputStream readObject():读取对象。使用此ObjectInputStream对象就可以完成反序列化动作

代码示例:

public class ObjectStreamDemo {

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

readObj();//对象的反序列化。

}

public static void readObj() throws IOException, ClassNotFoundException {

//1,定义流对象关联存储了对象文件。

FileInputStream fis = new FileInputStream("aa\\obj.txt");

//2,建立用于读取对象的功能对象。

ObjectInputStream ois = new ObjectInputStream(fis);

Person obj = (Person)ois.readObject();

System.out.println(obj.toString());

}

}

5、将用户信息存储到文件中与读取文件用户

5.1、用户实体类

代码示例:

import java.io.Serializable;

/*

*

* Serializable 接口

* 作用: 想要序列化,就必须实现这个 接口. 不用重写任何方法.  只是标记 一下.

*/

public class User  implements Serializable{

String name ;

String psw ;

int age;

public User() {

super();

}

public User(String name, String psw) {

super();

this.name = name;

this.psw = psw;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPsw() {

return psw;

}

public void setPsw(String psw) {

this.psw = psw;

}

@Override

public String toString() {

return "User [name=" + name + ", psw=" + psw + "]";

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((name == null) ? 0 : name.hashCode());

result = prime * result + ((psw == null) ? 0 : psw.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

User other = (User) obj;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

if (psw == null) {

if (other.psw != null)

return false;

} else if (!psw.equals(other.psw))

return false;

return true;

}

}

5.2、序列化存储

代码示例:

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectOutputStream;

/*

*  序列化和反序列化 

*  序列化: 从内存保存到硬盘 

*  反序列化 : 从硬盘读取到内存 .

*  操作的数据都是对象 .  都是Object

*/

public class Demo {

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

// 创建序列化 流对象 

ObjectOutputStream oos  = new ObjectOutputStream(new FileOutputStream("user.txt"));

User user = new User("老王", "laowang");//java.io.NotSerializableException: cn.javahelp_02.User

oos.writeObject(user);

oos.close();

}

}

5.3、反序列化读取

代码示例:

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.ObjectInputStream;

/*

* 读取序列化的信息, 反序列化. 

*/

public class Demo2 {

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

// 创建反序列化 流 .

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt"));

Object obj = ois.readObject();

System.out.println(obj);

if (obj instanceof User) {

User u = (User) obj;

String name = u.getName();

System.out.println(name);

}

ois.close();

}

}

在创建对象读取(报读取文件结尾异常)思考:不知道里面存储多少元素,但是读到结尾就报异常,这样怎么办。

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.ObjectInputStream;

/*

* 读取序列化的信息, 反序列化. 

*/

public class Demo2 {

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

// 创建反序列化 流 .

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt"));

Object obj = ois.readObject();

System.out.println(obj);

if (obj instanceof User) {

User u = (User) obj;

String name = u.getName();

System.out.println(name);

}

Object obj2 = ois.readObject(); //End Of File  Exception  读取文件结尾异常

System.out.println(obj2);

ois.close();

}

}

5.4、集合序列化解决不知道存储元素数问题

代码示例:

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.util.ArrayList;

/*

*  把集合序列化. 

*/

public class Demo3 {

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

ArrayList<User > arrayList = new ArrayList<>();

User user = new User("金莲","jinlian");

User user2 = new User("西门","daguanren");

User user3 = new User("大郎","cuibing");

arrayList.add(user);

arrayList.add(user2);

arrayList.add(user3);

//创建 序列化流

ObjectOutputStream oos  = new  ObjectOutputStream(new FileOutputStream("user2.txt"));

oos.writeObject(arrayList);

oos.close();

ObjectInputStream ois  = new ObjectInputStream(new FileInputStream("user2.txt"));

Object readObject = ois.readObject();

System.out.println(readObject);

// 强制 转换  在遍历  readObject  --> ArrayList<User>

ArrayList<User>  userList  = (ArrayList<User>) readObject;

for (User u : userList) {

System.out.println(u.getName() +" -- "+ u.getPsw());

}

}

}

6、序列化接口

当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。

同时当反序列化对象时,如果对象所属的class文件在序列化之后进行了修改,那么进行反序列化也会发生异常InvalidClassException。发生这个异常的原因如下:

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

该类包含未知数据类型

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

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

标记作用,当年的类没变,虽然添加了属性,但是可以

代码示例:

public class Person implements Serializable {

/*

*  serialVersionUID = 1L

*  只是一个对象的标记. 防止 你的类升级了, 对象 与类的信息 不一致.

*/

//给类显示声明一个序列版本号。

private static final long serialVersionUID = 1L;

private String name;

private int age;

public Person() {

super();

}

public Person(String name, int age) {

super();

this.name = name;

this.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;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + "]";

}

}

7、瞬态关键字transient

当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会被序列化了。

同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。

代码示例:

public class Person implements Serializable {

/*

* 给类显示声明一个序列版本号。

*

*只要被transient修饰了,序列化时这个属性就不会琲序列化了。不想保存

*/

private static final long serialVersionUID = 1L;

private static String name;

private transient/*瞬态*/ int age;

public Person() {

super();

}

public Person(String name, int age) {

super();

this.name = name;

this.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;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + "]";

}

}

相关文章

网友评论

      本文标题:从屌丝到架构师的飞越(IO流篇)-序列化流

      本文链接:https://www.haomeiwen.com/subject/mkovhctx.html