我想使用ObjectOutputStream.writeObject()
将Hashtable序列化为文件,但我希望编写器始终覆盖任何现有对象,以便只存在单个对象:
FileOutputStream fout = new FileOutputStream( f);
ObjectOutputStream writer = new ObjectOutputStream(fout);
writer.writeObject( hashtable);
writer.flush();
hastable在运行时间歇性更新,因此我使用辅助方法来保持其状态:
private void persistObject( Hashtable ht){
writer.writeObject( ht);
writer.flush();
}
问题是每次我调用writeObject()
时,都会在文件中附加一个新的hastable;有没有办法只覆盖文件中的任何内容,因此只保留一个对象?
答案 0 :(得分:8)
最简单的方法是关闭并重新打开文件,只需在persistObject()方法中重新运行此代码:
private void persistObject( Hashtable ht){
try (ObjectOutputStream writer = new ObjectOutputStream(new FileOutputStream(f))) {
writer.writeObject( hashtable);
writer.flush();
writer.close();
}
}
答案 1 :(得分:1)
如果要丢弃文件内容并再次开始在文件的开头写入,则可以获取其频道并重新定位内容。问题是,ObjectStreams使用了一些内部头文件,如果我们想要“重置”流,我们需要考虑它。
在实例化ObjectOutputStream
之后,存储初始位置(writeStreamHeader
写两条短路 - 消耗4个字节,但最好是通用而不是抱歉),以便您可以定位通道而不会覆盖标题
final long initialPosition = fout.getChannel().position();
然后,每次你必须写东西时,跳过初始字节(通过定位通道),重置流并写下你的对象:
//java 1.7
private void persistObject(Hashtable ht){
fout.getChannel().position(initialPosition);
fout.reset();
writer.writeObject(ht);
writer.flush();
}
//java 1.6
private void persistObject(Hashtable ht){
fout.getChannel().position(initialPosition);
fout.getChannel().truncate(initialPosition);
writer.writeObject(ht);
writer.flush();
}
正如@bgp所提到的,我不认为打开/关闭文件确实会引入那么多开销...而且我不认为在每次写入时截断和刷新到磁盘是有效的,或者保持文件流长时间打开是一个很好的做法(或安全),但仍然很容易入侵ObjectOutputStream
。
答案 2 :(得分:1)
您应该在persistObject中打开/写入/关闭ObjectOutputStream。你不应该在第0位截断文件.ObjectOuputStream有一个复杂的结构,不仅是对象数据,还有标题,类描述符等。截断会破坏它,导致在尝试读取时出现StreamCorruptedException。