Question
Is it possible to append to an ObjectOutputStream in Java?
FileOutputStream fos = new FileOutputStream(preferences.getAppDataLocation() + "history", true);
ObjectOutputStream out = new ObjectOutputStream(fos);
Answer
When using an ObjectOutputStream in Java, appending data directly to an existing stream poses specific challenges. Unlike regular output streams, ObjectOutputStream maintains metadata associated with the stream, making it incompatible with append operations in the conventional sense.
try {
// Read existing objects
List<Stuff> history = new ArrayList<>();
FileInputStream fis = new FileInputStream(preferences.getAppDataLocation() + "history");
ObjectInputStream in = new ObjectInputStream(fis);
while (true) {
Stuff stuff = (Stuff) in.readObject();
history.add(stuff);
}
} catch (EOFException e) {
// This exception is expected at the end of the file
} catch (IOException | ClassNotFoundException e) {
System.out.println(e.toString());
} finally {
in.close();
}
// Write all objects back along with the new object
try {
FileOutputStream fos = new FileOutputStream(preferences.getAppDataLocation() + "history");
ObjectOutputStream out = new ObjectOutputStream(fos);
for (Stuff stuff : history) {
out.writeObject(stuff);
}
out.writeObject(new Stuff(stuff));
out.close();
} catch (IOException e) {
System.out.println(e.toString());
}
Causes
- ObjectOutputStream initializes a header when it is first created, which designates the stream as a new output stream.
- Appending to an existing stream results in the "java.io.StreamCorruptedException" because the header information becomes inconsistent when the stream is not started over.
Solutions
- Instead of appending to an ObjectOutputStream, consider using a different ObjectOutputStream for writing objects, or use a single ObjectOutputStream to write all objects in one go.
- If appending is essential, you must read all objects into memory, close the existing stream, and then write back all objects, followed by the new object in a single session.
Common Mistakes
Mistake: Attempting to directly append new objects without properly handling existing objects.
Solution: To correctly append data, read all existing objects first, then write them back to the stream along with the new objects.
Mistake: Not closing streams, leading to resource leaks.
Solution: Always close your ObjectInputStream and ObjectOutputStream in a finally block to ensure resources are freed.
Helpers
- Java ObjectOutputStream
- append to ObjectOutputStream
- java.io.StreamCorruptedException
- serializing objects in Java
- write multiple objects Java