0

I'm saving objects from two array lists to a file and if I restart the application I have called a read method at the startup which will read the data from the file and add them to the array lists

But when reading from the file only the first object is been read and added to the list even when I add several objects to the array list and save to the file when reading only the first object is read

My Method to Read Objects from the File:

void readData() throws IOException{

    try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("systemData.txt"))) {
        doctorList.add((Doctor) in.readObject());
        consultations.add((Consultation) in.readObject());
    } catch (EOFException ignored){

    } catch (IOException | ClassNotFoundException e ) {
        e.printStackTrace();
    }catch (ClassCastException ignored) {
        
    }
    
}

My Method to Save Objects to the File:

@Override
public void saveFile() {

        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("systemData.txt"))) {
            for (Doctor doctor : doctorList) {
                out.writeObject(doctor);
                System.out.println("Doctor data saved to the file");
            }
            for (Consultation consultation: consultations){
                out.writeObject(consultation);
                System.out.println("Consultation data saved to the file");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

}
2
  • 1
    You can make it a whole lot easier by writing and reading two separate Lists, each in one go Commented Jan 3, 2023 at 22:22
  • ... also you reading method only reads one doctor, and than tries to read consultations (and probably fails with exception in that moment if second object is not of that instance). Commented Jan 3, 2023 at 22:25

1 Answer 1

0

As @Slaw hints at you need to inform the read method how many many Doctors to read, then the number of Consulations. In short readObject() does not read the collection, only a single item... that's because you wrote item by item.

Think of it like this:

Imagining stuffing 4 apples and 6 oranges into a legwarmer. When you write/put in, you call writeObject() 4+6 times. When you read you are pulling things out of the leg warmer from the other end (that's why I chose a leg warmer and not a sock!) and you they come out in exactly the order you put them in. But just like a leg warmer/sock you cannot immediately tell what is going to come out as the objects have similar size...

Certainly your code is quite wrote since you invoke readObject() just twice. So you read just one of the Doctors into the doctors collection then what happens? Well, the second readObject() reads a Doctor but your code tries to cast it into a Consultation which will raise a ClassCastException. Your code catches this but then swallows the Exception so you don't know that that happened! (Hence why it is always bad to have empty catch blocks.

With this low level approach, people develop their own protocols to define how to know what is coming out of the leg-warmer, like @Slaw suggests,. In rough code (I didn't check this compiled) it would be:

out.writeObject(doctorList.size());
for (Doctor doctor : doctorList) {
    out.writeObject(doctor);
}
out.writeObject(consultations.size());
for (Consultation consultation: consultations){
    out.writeObject(consultation);
}
out.flush();

then read

Integer expectedDoctors = (Integer) in.readObject();
for(int i=0; i<expectedDoctors; i++) { 
   doctorList.add((Doctor) in.readObject());
}
Integer expected Consultations = (Integer) in.readObject();
for(int i=0; i<Consultations; i++) { 
   consultations.add((Consultation) in.readObject());
}

A simpler approach would be not to write Doctor by Doctor but the whole collection in one go:

out.writeObject(doctorList);
out.writeObject(consultations;
out.flush();

then read

doctorList.addAll((List) in.readObject());
consultations.addAll((List) in.readObject());

Now you don't need the "here comes" counter. Note addAll() and the changed cast.

The other things you must do is call out.flush(); to ensure all the data has been written - essential if you were to wrap the output stream with a Buffer.

Sign up to request clarification or add additional context in comments.

1 Comment

As @Slaw hints at you need to inform the read method how many many Doctors to read You don't. Instead of reading them into a List you can simply read the List itself (after having written it obviously)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.