问题:

若通过ObjectOutputStream向一个文件中多次以追加的方式写入Object,为什么用ObjectInputStream读取这些Object时,会产生StreamCorruptedException

原因:

使用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应,ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标志头,因此,多次以追加方式向一个文件写入Object时,该文件将会包含多个标志头,所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产生StreamCorruptedException。

解决方案:

构造一个ObjectOutputStream的子类,并覆盖writeStreamHeader()方法,被覆盖后的writeStreamHeader()方法应判断是否为首次向文件中写入Object,是则调用super.writeStreamHeader();若否,即以追加方式写入Object时,则应调用ObjectOutputStream.reset()方法。

案例:

创建测试类,在控制台上显示添加学生信息,要求程序循环运行,并依次提示接收学生类的所有属性值,保存到学生对象中,再将学生对象保存到集合对象中,并提示“是否继续添加(y/n):”,如果选择“y”则继续添加,否则退出循环,并将保存学生数据的集合对象通过序列化保存到“student.dat”文件中。然后实现从“student.dat”文件中反序列化保存学生数据的集合对象,并遍历打印输出学生信息。

解决StreamCorruptedException的错误:

/**

* 这个类可以避免StreamCorruptedException

* @author Liao

*

*/

public class MyObjectOutputStream extends ObjectOutputStream {

//无参构造函数

public MyObjectOutputStream() throws IOException, SecurityException {

super();

}

//有参构造函数

public MyObjectOutputStream(OutputStream out) throws IOException {

super(out);

}

/**

* 重写writeStreamHeader()方法

*/

@Override

protected void writeStreamHeader() throws IOException {

// TODO Auto-generated method stub

return ;

}

}

工具类:

public class SerializableUtil implements Serializable{

private static final long serialVersionUID = 1L;

/**

* 序列化对象

* 用户传一个Object类型对象,和要序列化到的文件路径即可进行序列化

* @param obj对象

* @param path 对象要被序列化到的文件路径

*/

public static void serializObject(Object obj,String path){

//创建文件

File file = new File(path);

//判断文件是否存在

if (!file.exists()){

//如果文件不存在,就创建文件

try {

file.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

}

//创建ObjectOutputStream

ObjectOutputStream objectOutputStream = null;

try {

//定义FileOutputStream,用于创建ObjectOutputStream

OutputStream outputStream = new FileOutputStream(file, true);

if (file.length() < 1){

objectOutputStream = new ObjectOutputStream(outputStream);

} else {

objectOutputStream = new MyObjectOutputStream(outputStream);

}

//把对象序列化到文件中

objectOutputStream.writeObject(obj);

} catch (Exception e) {

e.printStackTrace();

} finally {//强制关闭ObjectOutputStream

try {

objectOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 反序列化一个对象

*

* @param path 要反序列的文件的路径

* @return 返回一个被反序列化的对象

*/

@SuppressWarnings("resource")

public static Object unserializObject(String path){

//定义一个对象

Object obj = null;

//创建一个文件

File file = new File(path);

try {

//创建文件输入流

InputStream inputStream = new FileInputStream(file);

//通过文件输入流创建ObjectInputStream

ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);

//获取一个对象

obj = objectInputStream.readObject();

} catch (Exception e) {

e.printStackTrace();

}

//返回一个对象

return obj;

}

/**

* 序列化一个集合

* 用户传一个集合和要序列化到的路径即可进行序列化

* @param collections 集合

* @param path 要序列化的路径

*/

public static void serializList(List collections,String path){

//创建文件

File file = new File(path);

//判断文件是否存在

if (!file.exists()){

//如果文件不存在,就创建文件

try {

file.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

}

//创建ObjectOutputStream

ObjectOutputStream objectOutputStream = null;

try {

//定义FileOutputStream,用于创建ObjectOutputStream

OutputStream outputStream = new FileOutputStream(file, true);

if (file.length() < 1){

objectOutputStream = new ObjectOutputStream(outputStream);

} else {

objectOutputStream = new MyObjectOutputStream(outputStream);

}

//遍历集合,然后把对象序列化到文件中

for (T collection : collections){

objectOutputStream.writeObject(collection);

}

} catch (Exception e) {

e.printStackTrace();

} finally {//强制关闭ObjectOutputStream

try {

objectOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 反序列化一个List集合

* 因为文件中有多个对象,如何在反序列化到末尾时,终止反序列化呢?

* 这里有一个技巧,我们可以通过一个死循环,一直读知道抛出EOFException时就break退出循环

* @param path路径

* @return 返回一个集合

*/

@SuppressWarnings("unchecked")

public static List unserializList(String path){

//创建一个文件

File file = new File(path);

//创建一个List集合用于存储反序列化后的对象

List collections = new ArrayList();

//定义ObjectInputStream

ObjectInputStream objectInputStream = null;

try {

//创建文件输入流

InputStream inputStream = new FileInputStream(file);

objectInputStream = new ObjectInputStream(inputStream);

//获取一个对象

while (true){

try {

//反序列化一个对象

T t = (T) objectInputStream.readObject();

//把该对象添加到集合中

collections.add(t);

} catch (EOFException e) {

break;

}

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

objectInputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

//返回一个对象

return collections;

}

}

测试类:

/**

* 测试类

* @author Liao

*

*/

public class SerializationTest {

public static void main(String[] args) {

Scanner in = new Scanner(System.in);

boolean flag = true;

//创建集合用于存放实体对象

List persons = new ArrayList();

while (flag) {

// 输入用户ID

System.out.print("请输入UID:");

Integer uid = in.nextInt();

// 输入用户名

System.out.print("请输入用户名:");

String uname = in.next();

// 输入性别

System.out.print("请输入性别:");

String gender = in.next();

//把Person对象存到集合中

persons.add(new Person(uid, uname, gender.equals("男")? Gender.MAN : Gender.WOMEN));

// 是否继续

System.out.print("是否继续? y/n:");

String ifContinue = in.next();

if (ifContinue.equals("n")) {

flag = false;

}

}

//序列化

SerializableUtil.serializList(persons, "D:\\liaozhongmin.txt");

//反序列化

List collections = SerializableUtil.unserializList("D:\\liaozhongmin.txt");

System.out.println(collections);

}

}

java序列化和反序列化工具_Java 序列化和反序列化工具类并解决StreamCorruptedException问题 | 学步园...相关推荐

  1. java中bean是什么_java中bean是什么意思?有什么作用 | 学步园

    Bean的中文含义是"豆子",顾名思义JavaBean是一段Java小程序.JavaBean实际上是指一种特殊的Java类,它通常用来实现一些比较常用的简单功能,并可以很容易的被重 ...

  2. java判断简体和繁体字_java获取系统语言(区分简体中文和繁体中文) | 学步园...

    之前做android应用时遇到过一个问题,就是根据语言的不同而显示不同的内容 网上很多代码都是错误的,起码无法区分简体和繁体,这里给出一种方法 不涉及android任何知识,所以就归类到java这边了 ...

  3. java 显示多行歌词_Java Swing制作多行滚动歌词显示控件 | 学步园

    首先上图一张,为最终制作的效果图,不喜欢或感到失望的朋友可以先行离开 大家已经看到效果图了.那么下面就介绍设计思路和源代码 首先要想显示歌词,就要对歌词文件进行抽象.下面这个类是对某一行歌词文件进行了 ...

  4. java序列化算法透析_Java序列化机制与原理的深入分析

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一 ...

  5. java序列化算法透析_Java序列化算法透析

    /** *  轉載請注明作者longdick    http://longdick.iteye.com * */ Java 序列化算法透析 Serialization (序列化)是一種將對象以一連串的 ...

  6. java输出set集合元素_java Set集合,HashSet类详细介绍

    下面要给大家介绍的就是java Set集合方面的内容,本文主要讲到了HashSet类的一些知识,主要包括了HashSet类的特点,HashSet 类的常用构造方法重载形式以及代码演示了创建两种不同形式 ...

  7. java jstack 工具_java命令之jstack工具

    1.总述 jstack是jvm虚拟机自带的一种堆栈分析工具,用于打印出给定的java进程或者core file或者远程调试服务的堆栈信息等.主要分为两个功能如下: a.针对活着的进程做本地的或者远程的 ...

  8. java socket 工具_java Socket简易聊天工具

    本文实例为大家分享了一款Socket简易聊天工具,希望大家喜欢. 代码运行如图,看起来还不错 服务端 package qiu; import java.awt.BorderLayout; import ...

  9. java 日历工具_java之日历处理工具类Calendar类

    编程语言 java之日历处理工具类Calendar类 字号+ 作者:小虾米 2016-11-08 12:43 Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR.MONTH.DAY_O ...

最新文章

  1. Ubuntu 12.10 拨号上网及停用方法
  2. vba去oracle数据后乱码,vba中读取utf-8文件乱码问题
  3. Netbeans配置Java SE嵌入式平台(树莓派)
  4. 为啥led灯用一年后暗了很多_嫌原车的卤素“蜡烛灯”太暗,想换掉,该选氙气灯还是LED灯?...
  5. Lightoj1014【基础题】
  6. 斐波那契数列的实现(简单递归和动态规划)
  7. [OS复习]设备管理2
  8. 【Python 必会技巧】对字典按照键(key)或者值(value)排序
  9. matplotlib绘图_使用matplotlib库绘图
  10. Codeforces Round #500 (Div. 2) C.Photo of The Sky
  11. 通过jQuery获取窗口的高度
  12. 橱柜高度与身高对照表_170身高和橱柜高度对照表 详细解析
  13. linux下mongodb的安装及启动
  14. Bootstrap-按钮
  15. javascript模板插件amaze.js
  16. ST、SC、FC、LC光纤接头区别
  17. 怎么才能够坚持做一件事并且把它做好?
  18. extern 关键字详解
  19. UVA 1600 Patrol Robert 巡逻机器人 (启发搜索BFS)
  20. squid笔记下载_Squid笔记

热门文章

  1. CPQuery, 解决拼接SQL的新方法
  2. idea配置 Tomcat Deployment添加时没有Artifact...选择的解决方案
  3. JsonMappingException:找不到类型[simple type,class]的合适构造函数:无法从JSON对象实例化
  4. File.separator或File.pathSeparator
  5. 尝试远程添加Git存储库时收到“致命错误:不是git存储库”
  6. 对volatile的理解
  7. 阿里云云盾-智能风控(公测)发布
  8. PhpStorm+Homestead+Xdebug调试Laravel
  9. 贵州省新农合业务系统容灾技术支撑服务项目
  10. zabbix_agentd.conf配置文件详解