sta*_*orn 10 java serialization append objectinputstream
至于现在,java.io.StreamCorruptedException当我尝试追加一个Object时,我会得到.我已经在互联网上搜索了一种克服这种情况的方法.到目前为止我找到的答案是无法完成的.解决此问题的方法是将对象写入列表,然后将列表写入文件.
但是每次添加新对象时我都要覆盖该文件.它似乎不是加班的最佳解决方案.
有没有办法将对象附加到现有的对象流?
这实际上很容易.当您要添加到现有流时,您需要使用覆盖的ObjectOutStream的子类,writeStreamHeader以便不在文件中间写入第二个标头.例如
class NoHeaderObjectOutputStream extends ObjectOutputStream {
public NoHeaderObjectOutputStream(OutputStream os) {
super(os);
}
protected void writeStreamHeader() {}
}
Run Code Online (Sandbox Code Playgroud)
然后只需使用标准的ObjectInputStream来读取整个文件.
我在这个主题上找到的最好的文章是:http: //codify.flansite.com/2009/11/java-serialization-appending-objects-to-an-existing-file/
覆盖ObjectOutputStream的"解决方案"完全错误.我刚刚调查了一个由此引起的错误(浪费了两个宝贵的日子).它不仅有时会损坏序列化文件,而且甚至设法读取而不抛出异常并最终提供垃圾数据(混合字段).对于那些难以置信的人,我附上了一些暴露问题的代码:
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) throws Exception {
File storageFile = new File("test");
storageFile.delete();
write(storageFile, getO1());
write(storageFile, getO2());
write(storageFile, getO2());
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(storageFile));
read(ois, getO1());
read(ois, getO2());
read(ois, getO2());
}
private static void write(File storageFile, Map<String, String> o) throws IOException {
ObjectOutputStream oos = getOOS(storageFile);
oos.writeObject(o);
oos.close();
}
private static void read(ObjectInputStream ois, Map<String, String> expected) throws ClassNotFoundException, IOException {
Object actual = ois.readObject();
assertEquals(expected, actual);
}
private static void assertEquals(Object o1, Object o2) {
if (!o1.equals(o2)) {
throw new AssertionError("\n expected: " + o1 + "\n actual: " + o2);
}
}
private static Map<String, String> getO1() {
Map<String, String> nvps = new HashMap<String, String>();
nvps.put("timestamp", "1326382770000");
nvps.put("length", "246");
return nvps;
}
private static Map<String, String> getO2() {
Map<String, String> nvps = new HashMap<String, String>();
nvps.put("timestamp", "0");
nvps.put("length", "0");
return nvps;
}
private static ObjectOutputStream getOOS(File storageFile) throws IOException {
if (storageFile.exists()) {
// this is a workaround so that we can append objects to an existing file
return new AppendableObjectOutputStream(new FileOutputStream(storageFile, true));
} else {
return new ObjectOutputStream(new FileOutputStream(storageFile));
}
}
private static class AppendableObjectOutputStream extends ObjectOutputStream {
public AppendableObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void writeStreamHeader() throws IOException {
// do not write a header
}
}
}
Run Code Online (Sandbox Code Playgroud)
如该文章所述,您可以使用以下解决方案之一:
解决方案#1:在单个流中伪造多个文件
...
将您的"事务"写入ByteArrayOutputStream,然后通过DataOutputStream将此ByteArrayOutputStream的长度和内容写入文件.
解决方案#2:重新打开并跳过
另一种解决方案涉及使用以下方
Run Code Online (Sandbox Code Playgroud)long pos = fis.getChannel().position();关闭文件,重新打开文件,然后在读取下一个事务之前跳到此位置.