最近写一个图书馆管理系统,对于用户的信息想用ObjectOutputStream来实现存储,可不知为何,只要用了FileOutputStream(InputStream,append)这个方法在文件末尾追加,总是会在用ObjectInputStream读出的时候出现StreamCorruptedException,实在无奈,我问了老师,也没有解决。。。最后在一个论坛里面找到了一篇文章,终于得到了解决。抱歉作者是谁忘记了。下面是我简单的把原作者的观点的总结:
用ObjectOutputStream写到文件时,会调用writeStreamHeader的方法,在写入你要写入的内容之前会先写入一个header,这样才会在读出的时候解析出来。但是如果用了FileOutputStream追加的方法,就会导致每次追加的时候都会写入那个header,而读的时候只需要第一个header,所以就会把后面的header当做是你写的Object的一部分,这样就导致了无法解析而出现异常。针对这个问题,原作者进行了一些改进,写了自己的ObjectOutputStream:
package tool;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class AppendableObjectOutputStream extends ObjectOutputStream {
private static File file;
private AppendableObjectOutputStream(OutputStream out,File file) throws IOException {
super(out);
}
public static AppendableObjectOutputStream getInstance(OutputStream out,File f) throws IOException{ //这个方法主要是解决file的传入问题
file=f;
return new AppendableObjectOutputStream(out,f);
}
@Override
protected void writeStreamHeader() throws IOException {
if(!file.exists()||(file.exists()&&file.length()==0)){
super.writeStreamHeader();
}
else {
super.reset();
}
}
}
用ObjectOutputStream写到文件时,会调用writeStreamHeader的方法,在写入你要写入的内容之前会先写入一个header,这样才会在读出的时候解析出来。但是如果用了FileOutputStream追加的方法,就会导致每次追加的时候都会写入那个header,而读的时候只需要第一个header,所以就会把后面的header当做是你写的Object的一部分,这样就导致了无法解析而出现异常。针对这个问题,原作者进行了一些改进,写了自己的ObjectOutputStream:
package tool;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class AppendableObjectOutputStream extends ObjectOutputStream {
private static File file;
private AppendableObjectOutputStream(OutputStream out,File file) throws IOException {
super(out);
}
public static AppendableObjectOutputStream getInstance(OutputStream out,File f) throws IOException{ //这个方法主要是解决file的传入问题
file=f;
return new AppendableObjectOutputStream(out,f);
}
@Override
protected void writeStreamHeader() throws IOException {
if(!file.exists()||(file.exists()&&file.length()==0)){
super.writeStreamHeader();
}
else {
super.reset();
}
}
}
非常感谢原作者!!!!
后来,我个人觉得用追加的方法实在是太麻烦了,有没有其他的方法可以解决这个问题呢。经过试验,我想到一个也许是下下策,但感觉比用追加的方法方便不少的方法。
我想我可不可以把我需要存储的东西都弄到一个对象里面呢,这样不是就可以一次性读写了,也不用追加。比如对图书馆得借阅人我写一个BorrowerList继承ArrayList<Borrower>,每次读出来都是一个BorrowerList对象,如果要添加,只需要调用该对象的addBorrower方法,就可以把心得借阅人信息存储到这个对象中,然后把这个对象再写回文件就可以了。感觉这样貌似有些浪费资源,不过个人觉得应对少量的数据还是没有问题的,亲测没有问题。当然,对大量数据,可能只能另寻高招了。。