`
hanmiao
  • 浏览: 58062 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Java 多次序列化对象到同壹個文件及反序列化的问题

 
阅读更多
这几天上班看了点 Java 的基础知识点,看到介绍序列化的基本问题是都是以介绍序列化对象和反序列化对象为例的,依此就想到了:要是壹次序列化多个对象,再或者不同时间多次序列化对象,应该怎么做,于是动手试了下,发现了不少问题,由于是小菜搞了好久上网找,才得以解决问题,废话不多说了,下面直接进入正题。

(壹)java序列化的基本原理知识:http://yuyiming.iteye.com/blog/1277089

(二)壹次序列化多个对象及多次序列化产生的问题
   对于壹次序列化多个对象的话,就是多次调用 writeObject() 方法就可以了。然而要注意的壹点就是在一次的序列化的过程中(写入文件到关闭文件的过程为一次序列化过程),ObjectOutputStream 对象写对象的话,会写入一个 header,也就是一次序列化的过程中会在文件开始的地方写入一个 Header 的信息到文件中,于此在多次序列化的过程中(如序列化一次关闭文件后,可能又需要往文件中序列化其他对象),此时就会继续在文件末尾(本次序列化的开头)写入 Header 的信息,如此如果进行反序列化的对象的时候会报如下错误:
java.io.StreamCorruptedException: invalid type code: AC

因为这是头的信息而不是对象的信息,为了解决这个办法,就必须在以后序列化的过程中不写入头文件即可,详细的解决办法见郑君华的博客:多次ObjectOutputStream出现的错误。总结如下:
1、用同壹個 ObjectOutputStream 写对象;
2、但是大部分时候,要不断往某个文件记录对象,这样按照上面的说法就要维护壹個 ObjectOutputStream,然而重启应用时候就会重新创建壹個 ObjectOutputStream 对象,此时如果还是想往刚才那个文件里写对象的话,就会追加一个 header。这样在读对象时读到这个位置就会报错。解决方法是重写 ObjectOutputStream 类的 writeStreamHeader() 方法;

(三)多次反序列化多个对象时的解决方法
   上面解决了多次序列化的问题,为此我们发现他们在反序列化对象的时候,必须要知道序列化了多少个对象,然后才能循环多少次把对象取出来,这样显然不是很方便,如果我文件和程序关闭了,我下次要是又想反序列化的时候,怎么才知道以前序列化了多少个对象呢?为此我们通过如下的方法来解决,因为在readObject()的时候,每次都是反序列化壹個对象,所以我们可以通过一个 while(true) 的循环来读取,当到文件最后的时候,会抛出EOFFileEnd的壹個异常,这样间接解决了判断结束的问题。代码如下:
public class SerializableTestListError {
	private static List<Object> listObject = new ArrayList<Object>();

	public static void main(String[] args) throws IOException {
		Student stu1 = new Student(01044444441, "yteng1", 204);
		Student stu2 = new Student(00444344441, "yteng2", 421);
		Car car1 = new Car("DazsAut00144444444444400o", "ShangHai", 2000400.0);
		Car car3 = new Car("DazsAuto114444444441", "ShangHai", 2000400.0);
		Car car2 = new Car("For14444444d", "JiangSu", 300040.00);
		listObject.add(car2);
		listObject.add(car1);
		listObject.add(car3);
		listObject.add(stu1);
		listObject.add(stu2);
		writeObject2File(listObject, "D:\\new.txt");
		try {
			readObjectFromFile("D:\\new.txt");
		} catch (SerializedException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void writeObject2File(List<Object> o, String fileName)
			throws IOException {
		File file = null;
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
			file = new File(fileName);
			fos = new FileOutputStream(file, true);
			if (file.length() < 1) {
				oos = new ObjectOutputStream(fos);
			} else {
				oos = new MyObjectOutputStream(fos);
			}
			for (int i = 0; i < o.size(); i++)
				oos.writeObject(o.get(i));

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fos != null)
					fos.close();
				if (oos != null)
					oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void readObjectFromFile(String fileName) throws Exception {
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try {
			fis = new FileInputStream(fileName);
			ois = new ObjectInputStream(fis);

			while (true)
				System.out.println(ois.readObject());

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("文件终止!~");
			e.printStackTrace(); // 此处解决序列化完成后的异常
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("输出结束~");
		} finally {
			try {
				if (fis != null)
					fis.close();
				if (ois != null)
					ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

这里我壹次序列化了多個对象,另外我们还可以用流机制反序列化多個对象。代码如下:
public class SerializableTest {
	private static List<Student> listStudentObject = new ArrayList<Student>();
	private static List<Car> listCarObject = new ArrayList<Car>();
	private static List<Object> listObject = new ArrayList<Object>();

	public static void main(String[] args) throws IOException {
		Student stu1 = new Student(001, "yteng11", 20);
		Student stu2 = new Student(002, "yteng22", 21);
		Car car1 = new Car("DazsAuto", "ShangHai", 200000.0);
		Car car2 = new Car("Ford", "JiangSu", 30000.00);
		writeObject2File(stu1, "D:\\date.txt");
		writeObject2File(stu2, "D:\\date.txt");
		writeObject2File(car1, "D:\\date.txt");
		writeObject2File(car2, "D:\\date.txt");

		try {
			readObjectFromFile("D:\\date.txt");
		} catch (SerilizableException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		for (Iterator<Car> iterCar = listCarObject.iterator(); iterCar
				.hasNext();) {
			System.out.println(iterCar.next());
		}
		for (Iterator<Student> iterStudent = listStudentObject.iterator(); iterStudent
				.hasNext();) {
			System.out.println(iterStudent.next());
		}

	}

	public static void writeObject2File(Object o, String fileName)
			throws IOException {
		FileOutputStream fout = new FileOutputStream(fileName, true);
		ObjectOutputStream sout = new ObjectOutputStream(fout);
		sout.writeObject(o);
		sout.close();
		System.out.println("写入对象成功!");
	}

	public static void readObjectFromFile(String fileName) throws Exception {

		FileInputStream fin = new FileInputStream(fileName);
		BufferedInputStream bis = new BufferedInputStream(fin);
		ObjectInputStream oip = null;
		while (true) {
			try {
				oip = new ObjectInputStream(bis); // 每次重新构造对象输入流
			} catch (EOFException e) {
				e.printStackTrace();
				System.out.println("已达文件末尾");// 如果到达文件末尾,则退出循环
				break;
			}
			Object object = new Object();
			object = oip.readObject();
			if (object instanceof Student) { // 判断对象类型
				listStudentObject.add((Student) object);
			} else if (object instanceof Car) {
				listCarObject.add((Car) object);
			}
		}
		oip.close();
		bis.close();
		fin.close();
	}
}


本文中所有相关源代码见附件。
分享到:
评论

相关推荐

    Java序列化多次追加到txt以及从txt反序列化

    在这个特定的场景中,我们关注的是如何使用Java序列化来多次追加对象到一个TXT文件,而不是覆盖原有的内容,以及如何从TXT文件中反序列化这些对象并显示在控制台上。 首先,要实现序列化,我们的类必须实现`...

    加快Java的文件序列化速度

    在Java编程中,文件序列化是一个常见的操作,用于将对象的状态转换为字节流,以便存储或在网络上传输。然而,序列化过程可能会消耗大量时间,尤其是在处理大量数据时。以下是一些加快Java文件序列化速度的方法: 1....

    java中对象的序列化

    如果同一个对象被请求序列化多次,系统会执行反引用序列化,避免重复写入字节流。 示例代码如下: ```java FileOutputStream fileOut = new FileOutputStream("file.ser"); ObjectOutputStream out = new ...

    Socket通信之序列化对象通信

    服务器接收并反序列化这个字节流,恢复出Student对象,从而完成了一次基于Socket的序列化对象通信。 总结,Socket通信结合对象序列化提供了一种有效的方式,让网络上的不同系统可以共享和交换自定义的Java对象。这...

    java不同对象及集合的多次复制

    - **序列化与反序列化**:将对象序列化为字节数组,然后再反序列化为新的对象,实现深拷贝。 3. **注解实现对象复制** - **Apache Commons BeanUtils库**:提供了`BeanUtils.copyProperties()`方法,可以快速实现...

    浅谈java中为什么实体类需要实现序列化

    在Java中,实体类需要实现序列化是因为序列化是将对象转换为字节流的过程,而反序列化是将字节流转换回对象的过程。在Java中,实现序列化的类需要实现java.io.Serializable接口,否则将会抛出异常。 首先,为什么...

    穿越字节的迷宫:Java中的序列化与反序列化之旅

    4. **多线程**:Java内置了对多线程编程的支持,允许开发者创建同时运行的多个线程。 5. **丰富的标准库**:Java拥有一个庞大的标准库,提供了大量预先构建的类和接口,简化了开发过程。 6. **高性能**:虽然Java...

    即时聊天(序列化)

    序列化是将对象的状态转换为可以存储或传输的数据格式的过程,而串行接口则是一种数据传输方式,它一次处理一个数据位,适合于低速但稳定的数据传输。 1. **序列化技术**:在即时聊天中,序列化扮演着关键角色,...

    JNDI加载RMIServer,对FastJson的反序列化攻击,.zip

    这个压缩包文件的标题“JNDI加载RMIServer,对FastJson的反序列化攻击”揭示了一个常见的安全漏洞,即FastJson的反序列化漏洞。让我们深入探讨这个话题。 首先,JNDI(Java Naming and Directory Interface)是一种...

    Java单例模式设计

    Java单例模式是一种常用的设计模式,它保证一个类只有一个实例,并提供全局...而考虑到序列化和反序列化的影响,我们需要额外处理以保持单例特性。在实际开发中,选择合适的单例模式可以提升代码的可读性和系统性能。

    MessagePack Java 示例程序

    `messagepack-6-demo-java-master`这个压缩包可能包含了多个示例,演示了不同类型的Java对象如何序列化和反序列化,包括基本类型、数组、列表、映射等。这些示例可能涵盖了多种场景,如网络通信、数据库存储、缓存等...

    《面向对象程序设计JAVA语言程序设计》期末考试试题及部分答案

    9. **IO流**:Java的IO流用于处理输入输出,包括字节流和字符流,以及对象序列化和反序列化。 10. **多线程**:Java内置对多线程的支持,可以创建并发执行的任务,提高程序性能。 在提供的“test.txt”文本文件和...

    Java大文件传输示例额

    1. 接收到一个数据块对象的字节流后,反序列化恢复成对象。 2. 按照接收到的数据块序号和长度,将数据存储到临时文件中,可以使用`FileOutputStream`进行写入操作。 3. 当接收到所有数据块并按顺序写入后,使用`...

    JSON序列化工具探析.pdf

    JSON序列化工具是指将Java对象转换为JSON格式的工具。JSON作为一种轻量级的客户端数据交换格式,经常被应用于Web应用程序中,是一种理想的数据交换格式。在开发软件的过程中,选择合适的JSON序列化工具是非常重要的...

    java源码包---java 源码 大量 实例

     Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

    java中读写XML文件

    JAXB提供了一种更便捷的方式来映射Java对象到XML以及从XML反序列化回Java对象。首先,你需要定义Java类,然后使用`jaxb绑定`生成相应的XML代码。例如: ```java // 假设我们有一个Employee类 Employee employee ...

    基于java开发的一个简单的文件发送与聊天程序

    4. **数据传输**:可能使用ObjectOutputStream和ObjectInputStream实现对象的序列化和反序列化,以便在网络上传输数据。 5. **聊天界面**:如果包含图形用户界面,可能使用了Java Swing或JavaFX库来创建用户界面。 6...

    java对象的 生命周期

    4. **反序列化**:通过`java.io.ObjectInputStream`的`readObject()`方法将序列化的对象恢复为内存中的对象实例。 #### 构造方法 构造方法是用于初始化对象的关键组件。它有以下几个特点和用法: - **重载构造...

    如何将java对象转换成xml

    - 使用`toXML()`方法将Java对象转换为XML字符串,或者使用`fromXML()`方法将XML字符串反序列化回Java对象。 4. **XML到Java对象的转换**: - JAXB的`Unmarshaller`类用于此操作,通过`unmarshal`方法从XML文件或...

Global site tag (gtag.js) - Google Analytics