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)); }