Loading

readObject 出现异常: java.io.StreamCorruptedException: invalid type code: AC

今天在项目上面遇到了这个问题:

代码背景

有一个类,在向数据库里面写数据,但是他写数据的方式是有缓存的,他在一定的时间里面接受数据存到自己的buffer里面,然后在特定的时间间隔里面写出去。

如果在buffer有数据的时候断开数据库连接,就会将buffer中的对象保存到文件中。然后在下一次往数据库写的时候读出来再写入数据库。

问题:

在使用ObjectInputSream#readObject的时候,出现了 java.io.StreamCorruptedException: invalid type code: AC异常。

分析:

经过一段时间的google,发现是在readObject的时候复用ObjectInputStream会出现该问题:

复现代码:

package ser;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author lijuny
 * @date 2020/12/23
 */
public class TestSer {
	private static final String PATH = "/Users/lijunyi/workdir/logs/o.obj";

	private static void writeFile(List<Student> studentList) throws IOException {
		File file = new File(PATH);
		if (!file.exists()) {
			file.createNewFile();
		}

		try (FileOutputStream outputStream = new FileOutputStream(file, true)) {
			for (Student student : studentList) {
				new ObjectOutputStream(outputStream).writeObject(student);
			}
		}
	}

	private static Student readStudent(FileInputStream fileInputStream, InputStream in) throws IOException, ClassNotFoundException {

		return (Student) new ObjectInputStream(in).readObject();
	}

	private static List<Student> readFile() throws IOException, ClassNotFoundException {

		List<Student> students = new ArrayList<>();
		try (FileInputStream fileInputStream = new FileInputStream(new File(PATH));
		     BufferedInputStream inputStream = new BufferedInputStream(fileInputStream);
		     ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
			while (inputStream.available() > 0) {
				students.add((Student) objectInputStream.readObject());
			}
		}
		return students;
	}

	private static List<Student> createStudents(String... names) {
		List<Student> students = new ArrayList<>(names.length);
		for (String name : names) {
			students.add(new Student(name));
		}
		return students;
	}

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		List<Student> students_1 = createStudents("A", "B", "D");
		writeFile(students_1);
		List<Student> students_2 = createStudents("D", "E", "F");
		writeFile(students_2);
		List<Student> students = readFile();
		System.out.println(students);
	}
}

Student类:

package ser;

import java.io.Serializable;

/**
 *
 * @author lijuny
 * @date 2020/12/23
 */
public class Student implements Serializable {
	private final String name;
	public Student(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student{" +
				"name='" + name + '\'' +
				'}';
	}
}

执行出现:

Exception in thread "main" java.io.StreamCorruptedException: invalid type code: AC
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1601)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
	at ser.TestSer.readFile(TestSer.java:49)
	at ser.TestSer.main(TestSer.java:68)

但是实际上,我编码的时候使用的并不是复用ObjectInputStream,而是每次readObject都创建了ObjectInputStream,应该不会出现这个问题。

后来知道了,此问题出现的原因是,每次outputStream写入数据的时候每个ObjectOutputStream都会将一个header写入到文件中。

ObjectInputStream靠这个header来去读取文件,但是在读到header之后又读取了到了header就会出现这个异常,也就是在一个对象的磁盘空间出现了两个header

最后只能靠检查代码,但是检查代码也没有发现任何异常,只能暂时放下这个问题,可能是写的时候那里出现问题了,但是具体是哪里不知道。

https://stackoverflow.com/questions/2393179/streamcorruptedexception-invalid-type-code-ac

posted @ 2020-12-23 20:31  lijuny  阅读(1091)  评论(2)    收藏  举报