Ajoutant à un ObjectOutputStream
Est-il pas possible d'ajouter à un ObjectOutputStream
?
Je suis en train d'ajouter à une liste d'objets. L'extrait de code suivant est une fonction qui est appelée chaque fois qu'un travail est terminé.
FileOutputStream fos = new FileOutputStream
(preferences.getAppDataLocation() + "history" , true);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject( new Stuff(stuff) );
out.close();
Mais quand j'essaie de le lire, je seulement obtenir la première dans le fichier.
Puis-je obtenir java.io.StreamCorruptedException
.
De lire, je suis en utilisant
FileInputStream fis = new FileInputStream
( preferences.getAppDataLocation() + "history");
ObjectInputStream in = new ObjectInputStream(fis);
try{
while(true)
history.add((Stuff) in.readObject());
}catch( Exception e ) {
System.out.println( e.toString() );
}
Je ne sais pas combien d'objets sera présente donc, je suis à la lecture il n'y a pas d'exceptions. À partir de ce que Google dit que c'est pas possible. Je me demandais si quelqu'un connaît un moyen?
- Obtenez-vous quoi que ce soit à partir du flux, ou faut-il lancer une exception la première fois autour de la boucle?
- il lit le premier objet que j'ai sauvé puis-je obtenir de l'exception.
- Dans le code ci-dessus, je ne suis qu'en voyant un objet écrit dans le fichier, donc un seul peut être lu, non?
- premier extrait est une fonction qu'il est appelé plusieurs fois à chaque fois qu'un travail est terminé. mais je ne peux que lire le premier que j'ai écrit.
- Ici votre code écrit seulement 1 objet de la rivière, est-il rien qui n'a pas montré que l'écrit plus de 1 objet de ce cours d'eau ?
Vous devez vous connecter pour publier un commentaire.
Voici l'astuce: sous-classe
ObjectOutputStream
et remplacer lewriteStreamHeader
méthode:À utiliser, il suffit de vérifier si le fichier de l'historique existe ou pas et d'instancier cette appendable flux (dans le cas où le fichier n'existe pas = nous append = nous ne voulons pas d'un en-tête) ou le flux d'origine (dans le cas où le fichier n'existe pas = nous avons besoin d'un en-tête).
Modifier
Je n'étais pas heureux avec la première appellation de la classe. C'est la meilleure: il décrit le "pour quoi il est' plutôt que le 'comment faire'
Modifier
Changé le nom une fois de plus, de préciser que ce flux est uniquement pour permettre l'ajout d'un fichier existant. Il ne peut pas être utilisé pour créer un nouveau fichier avec les données de l'objet.
Modifier
Ajouté un appel à
reset()
après cette question a montré que la version d'origine est simplement remplacéwriteStreamHeader
à un no-op pouvaient, dans certaines conditions, créer un flux qui n'a pas pu être lue.Comme le API dit, la
ObjectOutputStream
constructeur écrit la sérialisation en-tête de flux pour le flux sous-jacent. Et cet en-tête devrait être qu'une seule fois, en début de fichier. Afin de l'appelantplusieurs fois sur la
FileOutputStream
qui fait référence au même fichier va écrire l'en-tête à plusieurs reprises et de corrompre le fichier.En raison de la forme précise du fichier sérialisé, ajoutant sera en effet la corrompre. Vous devez écrire tous les objets dans le fichier en tant que partie d'un même ensemble, ou bien il va se bloquer lorsqu'il lit le flux de métadonnées lorsqu'il s'attend à un objet.
Vous avez pu lire le La Sérialisation Spécification pour plus de détails, ou (plus facile) lire ce fil où Roedy Green dit, fondamentalement, ce que je viens de dire.
La façon la plus simple pour éviter ce problème est de garder le OutputStream ouvrir lorsque vous écrivez les données, au lieu de le fermer après chaque objet. L'appel de
reset()
pourrait être souhaitable d'éviter les fuites de mémoire.L'alternative serait de lire le fichier comme une série consécutive de ObjectInputStreams ainsi. Mais cela vous oblige à garder compter le nombre d'octets que vous avez lu (ce qui peut être implementd avec un FilterInputStream), puis fermez le InputStream, l'ouvrir à nouveau, ignorer que nombre d'octets, et seulement alors, l'envelopper dans un ObjectInputStream().
Que diriez-vous avant chaque fois que vous ajoutez un objet, de lire et de copier toutes les données dans le fichier et d'écraser tous ensemble dans un fichier.