我的Java开发学习之旅------>Java使用ObjectOutputStream和ObjectInputStream序列号对象报java.io.EOFException异常的解决方法

本文涉及的产品
系统运维管理,不限时长
简介: 今天用ObjectOutputStream和ObjectInputStream进行对象序列化话操作的时候,报了java.io.EOFException异常。 异常代码如下: java.

今天用ObjectOutputStream和ObjectInputStream进行对象序列化话操作的时候,报了java.io.EOFException异常。

异常代码如下:

java.io.EOFException
	at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2554)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1297)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
	at cn.fuxi.io.ReadObject.readObject(ReadObject.java:27)
	at cn.fuxi.io.ReadObject.main(ReadObject.java:12)
这个异常是因为我使用 ObjectInputStream读取对象时候,没有判断好ObjectInputStream是否读取到了未知长度的文件末尾,导致到了文件末尾,程序无法正常读取文件内容。


后来研究了一下以后,得出三种解救思路:

第一种方法:

在写完对象后,加一句 oos.writeObject(null);  插入null是用来判断是否读取到结尾。oos是ObjectOutputStream实例。

  然后读对象的时候,使用while ((obj = ois.readObject()) != null),来判断再次读取一个对象,判定对象是否是空,如果不为null继续读取,如果为null停止读取。


第二种方法:

将若干个对象(数量不定)都装入 一个容器中(如:ArrayList之类的),然后写对象的时候,将该容器写入。

读取的时候,读取出容器,然后再遍历容器,取出自己所需的对象。


第三个方法:

和第二个方法类似,将对象都存入数组中,然后写入数组对象。

读取的时候,取出数组,再遍历数组,取出所需的对象。


下面是具体的代码操作:


1、要进行序列号的对象  Person.java


import java.io.Serializable;

public class Person implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -6374324573857634276L;
	private String name;
	private int age;

	public Person(String name, int age) {
		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;
	}

}

2、写入对象的三种方法    

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class WriteObject {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		writeObjectByArray();
		writeObject();
		writeObjectByList();
	}
	/**
	 * 直接写入对象
	 */
	private static void writeObject() {
		try {
			ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream("object.txt"));
			for (int i = 1; i < 10; i++) {
				oos.writeObject(new Person("欧阳鹏[" + i+"]", i));
			}
			//插入null是用来判断是否读取到结尾
			//写入结束标志方便读取(非常重要,如果不写入,在读取的时候无法定位读取结束);
			//读取的时候就会报  java.io.EOFException  异常
			oos.writeObject(null);
			oos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 通过数组写入对象
	 */
	private static void writeObjectByArray() {
		try {
			ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream("objectByArray.txt"));
			Person[] persons = new Person[10];
			for (int i = 1; i < 10; i++) {
				Person person = new Person("欧阳鹏 Arrays[" + (10+i)+"]", 10+i);
				persons[i] = person;
			}
			oos.writeObject(persons);
			oos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 通过集合写入对象
	 */
	private static void writeObjectByList() {
		try {
			ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream("objectByList.txt"));
			List<Person> persons=new ArrayList<Person>();
			for (int i = 1; i < 10; i++) {
				Person person = new Person("欧阳鹏 List[" + (20+i)+"]", 20+i);
				persons.add(person);
			}
			//写入List
			oos.writeObject(persons);
			oos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}


3、读取对象的三种方法    

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

public class ReadObject {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		readObject();
		System.out.println("==============================");
		readObjectByArrays();
		System.out.println("==============================");
		readObjectByList();
	}
	/**
	 * 直接读取对象
	 */
	private static void readObject() {
		try {
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
					"object.txt"));
			Object obj = null;
			//如果为null就读取到文件结尾了
			//读取结束标志位:是再次读取一个对象,判定对象是否是空,如果不为null继续读取,如果为null停止读取
			while ((obj = ois.readObject()) != null) {
				////反序列化读取得到Person
				Person person = (Person) obj;
				System.out.println("名字为:" + person.getName() + "  年龄为:"
						+ person.getAge());
			}
			ois.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 通过数组读取对象
	 */
	private static void readObjectByArrays() {
		try {
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
					"objectByArray.txt"));
			//反序列化读取得到Person[]
			Person[] persons = (Person[]) ois.readObject();
			for (int i = 1; i < persons.length; i++) {
				Person person = (Person) persons[i];
				System.out.println("名字为:" + person.getName() + "  年龄为:"
						+ person.getAge());
			}
			ois.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 通过集合读取对象
	 */
	private static void readObjectByList() {
		try {
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
					"objectByList.txt"));
			//反序列化读取得到List<Person>
			List<Person> persons = (List<Person>) ois.readObject();
			for (int i = 0; i <persons.size(); i++) {
				Person person=persons.get(i);
				System.out.println("名字为:" + person.getName() + "  年龄为:"
						+ person.getAge());
			}
			ois.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}


下面是结果:

写入对象后,在src同级目录下,生成3个文件,分别是object.txt 、objectByArray.txt、objectByList.txt   如下图所示。



读取对象,结果如下:

名字为:欧阳鹏[1]  年龄为:1
名字为:欧阳鹏[2]  年龄为:2
名字为:欧阳鹏[3]  年龄为:3
名字为:欧阳鹏[4]  年龄为:4
名字为:欧阳鹏[5]  年龄为:5
名字为:欧阳鹏[6]  年龄为:6
名字为:欧阳鹏[7]  年龄为:7
名字为:欧阳鹏[8]  年龄为:8
名字为:欧阳鹏[9]  年龄为:9
==============================
名字为:欧阳鹏 Arrays[11]  年龄为:11
名字为:欧阳鹏 Arrays[12]  年龄为:12
名字为:欧阳鹏 Arrays[13]  年龄为:13
名字为:欧阳鹏 Arrays[14]  年龄为:14
名字为:欧阳鹏 Arrays[15]  年龄为:15
名字为:欧阳鹏 Arrays[16]  年龄为:16
名字为:欧阳鹏 Arrays[17]  年龄为:17
名字为:欧阳鹏 Arrays[18]  年龄为:18
名字为:欧阳鹏 Arrays[19]  年龄为:19
==============================
名字为:欧阳鹏 List[21]  年龄为:21
名字为:欧阳鹏 List[22]  年龄为:22
名字为:欧阳鹏 List[23]  年龄为:23
名字为:欧阳鹏 List[24]  年龄为:24
名字为:欧阳鹏 List[25]  年龄为:25
名字为:欧阳鹏 List[26]  年龄为:26
名字为:欧阳鹏 List[27]  年龄为:27
名字为:欧阳鹏 List[28]  年龄为:28
名字为:欧阳鹏 List[29]  年龄为:29




==================================================================================================

  作者:欧阳鹏  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址http://blog.csdn.net/ouyang_peng

==================================================================================================


判断ObjectInputStream是否读到文件末尾,文件长度未知

判断ObjectInputStream是否读到文件末尾,文件长度未知

判断ObjectInputStream是否读到文件末尾,文件长度未知

相关文章
|
7天前
|
Java
java代码优化:判断内聚到实体对象中和构造上下文对象传递参数
通过两个常见的java后端实例场景探讨代码优化,代码不是优化出来的,而是设计出来的,我们永远不可能有专门的时间去做代码优化,优化和设计在平时
24 15
|
3月前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
111 43
Java学习十六—掌握注解:让编程更简单
|
2月前
|
Java
java 中 IO 流
Java中的IO流是用于处理输入输出操作的机制,主要包括字节流和字符流两大类。字节流以8位字节为单位处理数据,如FileInputStream和FileOutputStream;字符流以16位Unicode字符为单位,如FileReader和FileWriter。这些流提供了读写文件、网络传输等基本功能。
59 9
|
2月前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
3月前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
68 17
|
2月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
2月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
63 0
|
5月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。