ObjectOutputStream追加写入导致读取报错的问题分析
问题现象:使用ObjectOutputStream向同一个文件写入多个对象,
A). 当ObjectOutputStream在打开后连续写入多个对象再关闭,可通过ObjectInputStream正常读取写入的多个对象;
B). 当每写入一个对象即关闭ObjectOutputStream并在写入下一个对象时重新打开,通过ObjectInputStream读取对象时,可以正常读取第一个对象,但读取第二个对象时报错。典型的报错信息如下:
Exception in thread "main" java.io.StreamCorruptedException: invalid type code: AC at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at com.demo.ObjectSerializationDemo.writeObjectsSeparately(ObjectSerializationDemo.java:69) at com.demo.ObjectSerializationDemo.main(ObjectSerializationDemo.java:17)
问题原因:创建ObjectOutputStream对象时,会向输出流中写入标志数据“AC ED 00 05”;创建ObjectInputStream对象时,会自动解析输入流中开始的这些标志数据,因此采用方法A操作可以正常读取写入的对象。
但当采用方法B)时,由于ObjectOutputStream创建了两次,因此写入第二个对象时,会再次添加标志数据;ObjectInputStream仅能解析第一个对象前的标志数据,后面的标志数据当作对象数据处理,导致处理错误。
可参考这篇文章的内容。
方法A)示例程序:
public static void writeObjectsContinually() throws FileNotFoundException, IOException, ClassNotFoundException {
System.out.println("Write 2 Objects in one ObjectOutputStream:");
String[] array1 = {"this", "is", "a", "demo", "program"};
String[] array2 = {"this", "is", "also", "a", "demo", "program"};
File f1 = new File("object.out_1");
File f2 = new File("object.out_2");
/**
* 在一个OutputStream中写入array1和array2
*/
ObjectOutputStream outputStream;
outputStream = new ObjectOutputStream(new FileOutputStream(f1));
outputStream.writeObject(array1);
outputStream.writeObject(array2);
outputStream.flush();
outputStream.close();
/**
* 读取array1和array2
*/
ObjectInputStream inputStream;
inputStream = new ObjectInputStream(new FileInputStream(f1));
String[] arrayOut1 = (String[]) inputStream.readObject();
String[] arrayOut2 = (String[]) inputStream.readObject();
inputStream.close();
System.out.printf("==>>%s\n==>>before:%s\n==>>after:%s\n", "array1", Arrays.toString(array1), Arrays.toString(arrayOut1));
System.out.printf("==>>%s\n==>>before:%s\n==>>after:%s\n", "array2", Arrays.toString(array2), Arrays.toString(arrayOut2));
}
方法B)示例程序:
public static void writeObjectsSeparately() throws FileNotFoundException, IOException, ClassNotFoundException {
System.out.println("Write 2 Objects in two ObjectOutputStreams:");
String[] array1 = {"this", "is", "a", "demo", "program"};
String[] array2 = {"this", "is", "also", "a", "demo", "program"};
File f1 = new File("object.out_1");
File f2 = new File("object.out_2");
ObjectOutputStream outputStream;
/**
* 打开OutputStream,写入array1
*/
outputStream = new ObjectOutputStream(new FileOutputStream(f2, true));
outputStream.writeObject(array1);
outputStream.flush();
outputStream.close();
/**
* 打开OutputStream,写入array2
*/
outputStream = new ObjectOutputStream(new FileOutputStream(f2, true));
outputStream.writeObject(array2);
outputStream.flush();
outputStream.close();
/**
* 读取array1和array2
*/
ObjectInputStream inputStream;
inputStream = new ObjectInputStream(new FileInputStream(f2));
String[] arrayOut11 = (String[]) inputStream.readObject(); // 第一个对象读取成功
String[] arrayOut22 = (String[]) inputStream.readObject(); // 第二个对象读取时抛出异常
inputStream.close();
System.out.printf("==>>%s\n==>>before:%s\n==>>after:%s\n", "array1", Arrays.toString(array1), Arrays.toString(arrayOut11));
System.out.printf("==>>%s\n==>>before:%s\n==>>after:%s\n", "array2", Arrays.toString(array2), Arrays.toString(arrayOut22));
}