学习目标:
掌握序列化和反序列化的相关知识点,并去熟练运用
学习内容:
提示:这里可以添加要学的内容
例如:
1、 序列化:是对象到文件(把对象序列化后保存到磁盘中),所用的方法ObjectOutputStream
2、 反序列化:是文件到对象(读取磁盘中序列化的数据,重新恢复对象)
3、 序列化的步骤:准备序列化对象和序列化到哪里的目标文件的路径;序列化对象所在的类必须要实现序列化接口;创建序列化对象;使用流进行对象的序列化输出;关流
4、 反序列化的步骤:首先得有序列化的数据,通过反序列化恢复成对象;序列化版本号必须一致,不一致会报错;创建反序列化流对象;使用反序列化流恢复对象;关流。
5、练习:通过字节流和字符流完成文件复制的操作
代码如下(示例):
//写出对象运动员类
//如果本类想要完成序列化,必须实现可序列化接口,否则会报错
package serializable;
import java.io.Serializable;
public class Player implements Serializable {
//报错信息:java.io.NotSerializableException: cn.tedu.serializable.Player
//Serializable接口是一个空接口,里面一个方法都没有
private static final long serialVersionUID = 3379053834706454983L;
private String name;
private int age;
private char gender;
//创建无参构造
public Player() {
System.out.println("我是无参构造");
}
//创建有参构造
public Player(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
//创建get和set的所有方法
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 char getGender() {
return gender;
}
@Override
public String toString() {
return "Player{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
public void setGender(char gender) {
this.gender = gender;
}
}
//再重新建立一个类,用于测试序列化和反序列化
package serializable;
import java.io.*;
public class PlayerDemo {
public static void main(String[] args) {
f1();//测试序列化
f2();//测试反序列化
}
private static void f2() {
ObjectInputStream in = null;
try {
//创建流对象
in = new ObjectInputStream(new FileInputStream("E:\\ready\\1.txt"));
Object o = in.readObject();
System.out.println(o);
System.out.println("反序列化成功");
} catch (Exception e) {
System.out.println("反序列化失败!");
e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void f1() {
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream("E:\\ready\\1.txt"));
Player s = new Player("小陈",23,'女');
out.writeObject(s);
System.out.println("序列化成功");
} catch (IOException e) {
System.out.println("序列化失败");
e.printStackTrace();
}finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
总结:关于序列化版本号不一致报错的解决方案
1.手动添加UID(指 将UID的值写死,怎么样都不会变)可以任意序列化与反序列化
private static final long serialVersionUID = 1L;
2.不手动添加,自动生成,那就需要注意,每次编译都会生成一个新的UID
所以一次序列化需要对应一次反序列化,如果更改对象类(Player)类中的内容
一定要先序列化再反序列化,不然就报错
测试字节流和字符流对文件的复制,代码如下:
package io;
import java.io.*;
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
System.out.println("请输入要复制的源文件路径");
String from = new Scanner(System.in).nextLine();
System.out.println("请输入目标文件");
String t = new Scanner(System.in).nextLine();
//f1(from,t);//测试字符流复制
f2(from,t);//测试字节流复制
}
private static void f2(String from, String t) {
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(new FileInputStream(from));
out = new BufferedOutputStream(new FileOutputStream(t));
int a;
while ((a=in.read())!=-1){
out.write(a);
}
System.out.println("复制成功");
} catch (Exception e) {
System.out.println("复制失败");
e.printStackTrace();
}
}
private static void f1(String from,String t) {
Reader in = null;
Writer out = null;
try {
in = new BufferedReader(new FileReader(from));
out = new BufferedWriter(new FileWriter(t));
int a;
while ((a=in.read())!=-1){
out.write(a);
}
System.out.println("复制成功");
} catch (Exception e) {
System.out.println("复制失败");
e.printStackTrace();
//关流操作
//关流是有顺序的;如果有多个流,最后创建的流最先关闭
// 而且多条流语句需要各自try-catch
}finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}