The problem is that the ObjectOutputStream
writes a header to the file. When you open new output streams this header is written several times in the middle of the file.
The classic solution would be to leave the ObjectOutputStream
open (which may not be desirable). A second alternative would be to open several ObjectInputStream
s as per @mgibsonbr’s response; each of them reads a header (however, as he himself pointed out this may have implications; I get a little uncomfortable not closing resources).
However, in an answer in SOEN the user Andreas_d pointed out a very interesting solution involving overwriting the method writeStreamHeader()
with a call to reset()
.
public class AppendingObjectOutputStream extends ObjectOutputStream {
public AppendingObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void writeStreamHeader() throws IOException {
reset();
}
}
Logic of use (adaptation of the original answer):
Check whether the file exists or not, and then ask stream adequate:
In case the file exists we are "appending" and do not want a header:
ObjectOutputStream oos = new AppendingObjectOutputStream(fos);
In case the file does not exist we need a header:
ObjectOutputStream oos = new ObjectOutputStream(fos);
You can even encapsulate this logic in a method:
// Esboço; no código real trate exceções
public ObjectOutputStream openStream(File f) throws Exception {
ObjectOutputStream oos = null;
if (f.exists()) {
FileOutputStream fos = new FileOutputStream(f, true);
oos = new AppendingObjectOutputStream(fos);
} else {
FileOutputStream fos = new FileOutputStream(f);
oos = new ObjectOutputStream(fos);
}
return oos;
}
And the use of stream is transparent:
File f = new File("files\\Produtos.dat");
ObjectOutputStream oos = openStream(f); // Produtos.dat pode existir ou não
oos.writeObject(p);
oos.close();
oos = openStream(f); // Produtos.dat existe, apenda
oos.writeObject(p2);
oos.close();
// Versão Java 7 com try-with-resources
try (ObjectOutputStream oos = openStream(f)) {
oos.writeObject(p3);
}
P.S. The JEP 187 is exactly researching failures and possible improvements in the Java Serialization mechanisms. Maybe something interesting comes out of this research effort.
No need to close the file itself (fos) in addition to the stream (oos) at each cycle?
– epx
@epx It’s been a while since I’ve programmed in Java, but from what I remember when I closed a
Stream
it propagates it to the other streams it depends on (i.e. theoos
will close thefos
automatically).– mgibsonbr
Blz, the real problem was found and answered
– epx