Le meilleur article que j'ai trouvé sur ce sujet est: http://codify.flansite.com/2009/11/java-serialization-appending-objects-to-an-existing-file/
La « solution » qui remplace ObjectOutputStream est tout simplement faux. Je viens de finir d'enquêter sur un bug qui a été causé par cela (gaspillant deux jours précieux). Non seulement cela corromprait parfois le fichier sérialisé, mais même réussi à lire sans jeter des exceptions et à la fin fournir des données de poubelle (champs de mélange). Pour ceux dans l'incrédulité, j'attacher un code qui expose le problème:
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
}
}
}
Comme il est indiqué dans cet article, vous pouvez utiliser l'une des solutions suivantes:
Solution # 1: Faux plusieurs fichiers dans un seul flux
...
écrivez votre « transaction » à un ByteArrayOutputStream, puis écrire le longueur et le contenu de ce ByteArrayOutputStream à un fichier via le DataOutputStream.
Solution # 2: Ouvrez de nouveau et Passer
Une autre solution consiste à sauver la position de fichier en utilisant:
long pos = fis.getChannel().position();
fermeture du dossier, la réouverture du fichier, et sauter à cette position avant de lire la prochaine transaction.
Avez-vous une question? – danben
Est-il possible pour vous d'utiliser une base de données pour la persistance? – Asaph
@danben: oui, la question est de savoir si les objets peuvent être ajoutés à un fichier. @Asaph: Je pourrais le faire, mais je veux savoir si append est non pour les objets. Sry si ma question n'a pas clarifié cela. – starcorn