您的位置:首页 > 编程语言 > Java开发

java.io.StreamCorruptedException: invalid type code: AC

2017-06-20 22:01 537 查看
问题情景: 

问题描述: 用类ObjectOutputStream向文件写读对象时,碰到一个问题:新建一个文 
  件,用输出流ObjectOutputStream向文件连续写几个对象,关闭输出流,然 
  后读取,这些对象都可以读出;这时在向该文件增加对象,新写的对象就读不出了,不知什么原因?请教了! 
  
  问题出现的原因:ObjectOutputStream建立后第一次写入一个对象时, 会在对象数据前写入一些标志的数据“AC ED 
  00 05”(用ultraEdit打开),应该是流相关的信息。当你关闭 
  ObjectOutputStream后再重新打开往文件里面写对象时(append方式),就会再一次把“AC ED 00 
  05”写入文件,而这些信息并不是你写入对象的数据,所以当你用ObjectInputStream来读取对象时,流会将除第一个“AC ED 00 
  05”以外的数据当作各个对象的数据,造成无法解析,所以读取时有一个java.io.StreamCorruptedException出现。 
  这个可以通过编辑Info.dat来验证,只要将“AC ED 00 05”删除(第一个“AC ED 00 05”保留)就可以正常读出后来加入的对象。 
  给出一个比较笨的解决方法: 在以后要添加新的对象到Info.dat时,将里面原有的对象读出放入ArrayList中,清空文件,再将对象集一次写入。 
  
  尝试解决办法: 那个“AC
ED 00 05”是 
  ObjectOutputStream.writeSystemHeader()写进去的,你可以继承ObjectOutputStream类,覆盖这个方法。 
  在你自己的writeSystemHeader()里判断是不是第一次写入一个文件,如果是向一个文件大小不为零的文件追加的话,就调用 
  super.reset(),如果是第一次写这个文件,不是追加,就调用super.writeSystemHeader() 

自定义类MyObjectOutputStream 

package com.bjsxt.io.obj;

import java.io.*;

public class MyObjectOutputStream extends ObjectOutputStream {
// 定义成静态的好处
private static File f;

/**
* 初始化静态文件对象,并返回类对象
*
* @param file
* 文件对象,用于初始化静态文件对象
* @param out
* 输出流
* @return MyObjectOutputStream
* @throws IOException
*/
public static MyObjectOutputStream newInstance(File file, OutputStream out) throws IOException {
f = file;// 本方法最重要的地方:构建文件对象,是两个文件对象属于同一个
return new MyObjectOutputStream(out, f);
}
@Override
protected void writeStreamHeader() throws IOException {
if (!f.exists() || (f.exists() && f.length() == 0)) {
super.writeStreamHeader();
} else {
super.reset();
}

}

public MyObjectOutputStream(OutputStream out, File f) throws IOException {
super(out);
}

}


对象输出类
package com.bjsxt.io.obj;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

/**
* 序列化:将对象保存到磁盘内
* 1. 如何实现序列化?
* 类实现接口 会产生 version ID
* default
* 动态生成 属性值不同 ID也不同
* public class Student implements Serializable
* 2.某个属性不想被序列化
* 属性前+static
* transient
*
* 反序列化:读取到磁盘内的对象数据
* @author Mr.Gao
*
*/
public class ObjectOutPutStreamTest {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
//1.新建流对象
//节点流
File file = new File("D:\\object.txt");
OutputStream os = new FileOutputStream(file,true);
//缓冲流
BufferedOutputStream bos = new BufferedOutputStream(os);
//处理流
//ObjectOutputStream oos = new ObjectOutputStream(bos);
MyObjectOutputStream oos = MyObjectOutputStream.newInstance(file, bos);
//2.写出数据
Student s1 = new Student("李白", 34, 99);
Student s2 = new Student("杜甫",32,89);
System.out.println(file.length());

oos.writeObject(s1);
oos.writeObject(s2);
System.out.println("写出完毕");
//3.关流
oos.close();

}
}


读取对象流:
package com.bjsxt.io.obj;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
* 反序列化: 读取磁盘上的对象 反序列化时 反序列化的ID 必须与序列化的ID一致
*
* @author Mr.Gao
*/
public class ObjectInputStreamTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
// 创建对象输入流对象
// 读取对象
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("D:\\object.txt")));
Object readObject = null;

readObject = ois.readObject();
// readObject = ois.readObject();
System.out.println(readObject);

System.out.println(ois.readObject());
System.out.println(ois.readObject());
// 关流
ois.close();
}
}


实体类
package com.bjsxt.io.obj;

import java.io.Serializable;

public class Student implements Serializable{

private static final long serialVersionUID = 21L;
private String name;
private int age;
//private int id;
public Student(String name, int age, double score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
public Student() {
super();
}
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;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐