0

I have a number of objects (of the same class) serialized into a file. But while deserializing it, only the first serialized object is deserialized.

Code for serializing:

public void save() {
File f = new File("vehicule.txt");
try {
    if(!f.exists()) f.createNewFile();
} catch(IOException e) {
}
try {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f,true));
oos.writeObject(this);
} catch(IOException e) {
}

}

I think the problem is with:

Vehicule v;
while( (v = (Vehicule)ois.readObject()) != null )

Is there a better way to check for the end of the file?

user207421
  • 305,947
  • 44
  • 307
  • 483
Nice Books
  • 1,675
  • 2
  • 17
  • 21
  • Can you show how you are serializing the objects to the file? It looks like you are doing a custom serialization process. – Alejandro Diaz Dec 04 '11 at 23:13
  • 2
    You don't say what your problem actually is, and seeing how you catch and then discard exceptions, it's unlikely that you'll be able to say what it is. – kdgregory Dec 04 '11 at 23:39
  • An ObjectOutputStream does not produce a text file. It is binary. – user207421 Dec 04 '11 at 23:58

5 Answers5

1

It's probably better to write the number of Vehicules that are in the file at the beginning, and let that control how many you read.

If you want to do it the way you are doing it, then you will have to try/catch an IOException

[also btw, this isn't a txt file]

MeBigFatGuy
  • 28,272
  • 7
  • 61
  • 66
1

If you are going to use multiple appended ObjectOutputStreams, then I believe this might help (along with making sure you delete the file each time you run your test!):

Why can't a file that contains multiple appended ObjectOutputStreams be deserialized by one ObjectInputStream?

Using the default implementation of serialization, there must be a one-to-one mapping between ObjectOutputStream construction and ObjectInputStream construction. ObjectOutputStream constructor writes a stream header and ObjectInputStream reads this stream header. A workaround is to subclass ObjectOutputStream and override writeStreamHeader(). The overriding writeStreamHeader() should call the super writeStreamHeader method if it is the first write to the file and it should call ObjectOutputStream.reset() if it is appending to a pre-existing ObjectOutputStream within the file.

Otherwise I would suggest you add the objects to a List and then serialize it with a single ObjectOutputStream.

For example:

    Vehicule v1 = new Vehicule();
    Vehicule v2 = new Vehicule();
    List<Vehicule> vehicules = Arrays.asList(v1, v2);

    // serialize the list of Vehicules
    File f = new File("vehicule.txt");
    try {
        ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(f));
        oos.writeObject(vehicules);
        oos.close();
    } catch (Exception e) {
        e.printStackTrace(); // handle this appropriately
    }

    // deserialize the list of Vehicules
    try {
        ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(f));
        List<Vehicule> deserializedVehicles = (List<Vehicule>) ois.readObject();
        ois.close();
        System.out.println("list size = " + deserializedVehicles.size());
    } catch (Exception e) {
        e.printStackTrace(); // handle this appropriately
    }

For me, this outputs:

list size = 2
James Bassett
  • 9,458
  • 4
  • 35
  • 68
  • I tried that with ArrayList. Didn't work either – Nice Books Dec 04 '11 at 23:34
  • Now you've added the serialization code, it looks to me like you've implemented a save() method on the `Vehicule` class (`oos.writeObject(this);`). To serialize as a List you'd have to serialize all of the Vehicules outside that class (in one method call). – James Bassett Dec 04 '11 at 23:50
  • @NiceBooks Define "didn't work". – user207421 Dec 04 '11 at 23:58
  • Did you try serializing using just 1 ObjectOutputStream (i.e. not appending to the existing file) and a List? – James Bassett Dec 05 '11 at 00:01
  • Won't this code erase the previous vehicule objects which had been there in that file. – Nice Books Dec 14 '11 at 15:38
  • 1
    Yes, that's kind of the point. You have to serialize in one go - if you don't then you won't be able to de-serialize it (because there will be multiple headers in the one file). If you want to retain the previous vehicles, then create a new file each time. – James Bassett Dec 14 '11 at 21:54
0
try {
    if(!f.exists()) f.createNewFile();
} catch(IOException e) {
}

You don't need any of that. new FileOutputStream() will create the file.

new ObjectOutputStream(new FileOutputStream(f,true))

You can't append to an ObjectOutputStream. There are headers in there that ObjectInputStream won't understand if it encounters them in the middle of a stream.

while( (v = (Vehicule)ois.readObject()) != null )

Is there a better way to check for the end of the file?

There's nothing in the Javadoc about readobject() returning null at EOS. readObject() returns null if and only if you wrote a null.

The correct technique is to catch EOFException, close the stream, and break out of the loop.

user207421
  • 305,947
  • 44
  • 307
  • 483
0

Just serialize/deserlialize an ArrayList<Vehicle> (rather than trying to stuff multiple object into a single file).

Bohemian
  • 412,405
  • 93
  • 575
  • 722
0

Ok this is how it finally worked.
I deserialized everything in the file to an ArrayList; added the new object and while serializing, I added each element of the ArrayList to the file [erasing the previous entries by using (new FileOutputStream(new File("Vehicule.txt"),false) ].
Finally I added a null explicitly to the file so as to help with the deserializing.
Also while creating the file for the first time with createNewFile, I added a null to the file.

Mark Hall
  • 53,938
  • 9
  • 94
  • 111
Nice Books
  • 1,675
  • 2
  • 17
  • 21