import java.io.*;
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "姓名:" + name + ";年龄:" + age;
}
}
public class Text{
static int geshu = 0;
public static void main(String[] args) throws Exception
{
String path = "d:" + File.separator + "test.txt";
File f = new File(path);
Person p1 = new Person("张三", 23);
write(f, p1);
read(f, geshu);
Person p2 = new Person("李四", 32);
write(f, p2);
read(f, geshu);
}
public static void write(File f, Object p) throws Exception
{
OutputStream out = new FileOutputStream(f, true);
//true表示追加
MyObjectOutputStream oos = MyObjectOutputStream.newInstance(f,
out);
oos.writeObject(p);
geshu++;
oos.close();
System.out.println("-----Oject写入成功....");
}
public static void read(File f, int geshu) throws Exception
{
FileInputStream in = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(in);
for (int i = 0; i < geshu; i++) {
System.out.println((Person) ois.readObject());
}
ois.close();
}
}
new一个ObjectOutputStream的时候,这个ObjectOutputStream的构造方法就会调用writeStreamHeader()方法,
这样流中就会被写入了一些信息,这些信息也会写入到我们的文件中。在第一次写入文件时,这些头部信息是需要的。因为ObjectInputStream读的时候会帮我们过滤掉。但是当我们追加写入一个文件时,这些头部信息也会写入文件中,读取的时候只会把文件第一次出现的头部信息过滤掉,并不会把文件中间的头部信息也过滤掉,所以追加多个对象后,读取对象时会出现问题。
怎么解决呢?
一、不用追加,可以在每次写入的时候把文件中所有对象读出来,再将这些对象和要写入的对象一起重新写入。
二、如果不是第一次写入文件,在写入时去掉头部信息,怎么去掉呢?头部信息是在writeStreamHeader();方法中写入的,所以我们可以通过继承ObjectOutputStream来覆盖这个方法,如果不是第一次写入文件,这个方法什么也不做。
class MyObjectOutputStream extends
ObjectOutputStream {
private static File f;
writeStreamHeader()方法是在ObjectOutputStream的构造方法里调用的
由于覆盖后的writeStreamHeader()方法用到了f。如果直接用构造方法创建
一个MyObjectOutputStream对象,那么writeStreamHeader()中的f是空指针
因为f还没有初始化。所以这里采用单态模式
(将构造方法定义为私有的,然后通过方法获取对象,可以保证某个类只能存在一个对象示例)
public static MyObjectOutputStream newInstance(File file,
OutputStream out)
throws IOException {
f = file;
return new MyObjectOutputStream(out);
}//通过方法初始化f,获取对象。
private MyObjectOutputStream(OutputStream out) throws IOException
{
super(out);//会调用重写的writeStreamHeader()方法
}//不能在类的外部使用new,但在类的内部可以
@Override
protected void writeStreamHeader() throws IOException {
if (!f.exists() || (f.exists() &&
f.length() == 0)) {
super.writeStreamHeader();
} else {
super.reset();
}
}
}