-1

Trying to make a Program that writes and reads Multiple Serialized Objects to a file as necessary(random access or even serial).I have appended multiple objects to my file but cant load more than one, i get IOException. The writes happen multiple times before trying to read so it does not find EOF.

Object Class

public class Account implements Serializable {

private static final long serialVersionUID = 1L;

private String firstName;
private String lastName;
private String age;
private String telephone;
private String program;
private String gender;
private double balance;

Write

try {

    FileOutputStream fileOut = new FileOutputStream("Database.dat", true);
    ObjectOutputStream DatabaseOut = new ObjectOutputStream(fileOut);
    DatabaseOut.writeObject(AccToWrite);
    DatabaseOut.close();
    fileOut.close();
    //dbg
    JOptionPane.showMessageDialog(null, "Account Was Registerd", "Registration", JOptionPane.INFORMATION_MESSAGE);
}

Read

try {
    FileInputStream fis = new FileInputStream("Database.dat");
    ObjectInputStream ois = new ObjectInputStream(fis);

    Account tempaccount = (Account) ois.readObject();
    System.out.println(tempaccount.toString());

    Account tempaccount2 = (Account) ois.readObject();
    System.out.println(tempaccount2.toString());

    fis.close();
    ois.close();
} catch (FileNotFoundException x) {
    System.out.println("File not found");
} catch (IOException x) {
    System.out.println("Error initializing stream");
}

Any help is much appreciated.

Fildor
  • 12,873
  • 4
  • 34
  • 64
Empty
  • 64
  • 1
  • 7

1 Answers1

0

Your writer is only writing one object before you close the stream. I think this is likely what's causing your issue in the reader code - you're trying to read more than one Account, but you only wrote one, so it's hitting EOF by the time you try to read that second Account. You need to write all Account objects you intend to write first before closing the stream. If your reader doesn't know ahead of time how many Account objects it should read, the best solution would be to have the writer call writeObject(null) after writing all of the objects it expects to, then have the reader call ois.readObject() in a while loop until that method returns null. Then, you know that there are no more objects to be read from the stream.

Another potential issue is you're explicitly closing both nested streams in your writer and reader code. You technically only need to close one (preferrably the outer ObjectInput/OutputStream instances). You can actually do this really easily by using a try-with-resources block:

//Writer
try(FileOutputStream fileOut = new FileOutputStream("Database.dat", true);
        ObjectOutputStream DatabaseOut = new ObjectOutputStream(fileOut)){
    //Do all your Account object writing here ...
    DatabaseOut.writeObject(null);
} //By this point, Java has automatically closed the streams for you.

You can do the same thing with your reader code. Just be careful not to close the stream before you're done writing/reading all of the objects you expect to write/read.

CodeBlind
  • 4,409
  • 1
  • 22
  • 34
  • `readObject()` does not return null at end of stream. It throws `EOFException`. – user207421 Apr 21 '20 at 21:41
  • 1
    @user207421 I should have been more clear. Best practice is to write a null at the end of the writing process so you know you've successfully reached the end of the stream when reading (otherwise you wouldn't be able to distinguish between expected and unexpected EOF exceptions). I've updated my answer. – CodeBlind Apr 22 '20 at 21:27
  • 1
    'Best practice' is to catch the `EOFException`. Your way you are inhibiting yourself from writing null at any other time, which is a major loss of functionality, and you are also relying on the null getting written, and you still have to handle the `EOFException` anyway in case it wasn't. – user207421 Apr 23 '20 at 02:37
  • 1
    I never said `EOFException` shouldn't be caught. I'm merely pointing out that Exceptions indicate a disruption to the normal flow of instructions (https://docs.oracle.com/javase/tutorial/essential/exceptions/). Under "normal" circumstances, `FileInputStream` can't stream data forever (because the file system has finite memory), so why would you write code that expected them to, and then rely on a caught Exception, something reserved for abnormal circumstances, to indicate normal behavior? – CodeBlind Apr 23 '20 at 06:04
  • OMG not another one. The exception is exceptional because it only happens at end of stream, not that it matters in the slightest. Exceptions are not 'reserved': or perhaps you could say that this one is 'reserved' for end of stream, and that is when it is thrown. The API is designed to throw `EOFException` at end of stream, and that is what you should catch to detect it. You haven't addressed my point about nulls. Don't describe things as 'best practice' just because you thought of them. – user207421 Apr 24 '20 at 03:02
  • I disagree with your point about nulls. There. I've addressed it. The API doesn't throw an `EOFException` at the end of the stream, it throws one when you've attempted to read PAST the end of the stream. I said "best practice" because it's what I've seen done *many* times throughout my 15 year career professionally writing Java HPC code, not because I thought it up out of thin air. Should I have included that in my answer as well?? Whatever. Have a nice day. – CodeBlind Apr 24 '20 at 03:25
  • It throws an exception when you read and you're already at end of stream. There is nothing to argue about there. As to the rest, you're flogging a dead horse. If the API designers had wanted to return a null at end of stream they would have done so. They didn't, for the reason I gave above, which you still haven't addressed. I'm not interested in discussing exception phobias. I've been programming in Java for 23 years and I have never seen code such as you describe, except here. Just becasue you saw it doesn't make it best practice. Best practice is to use the API the way it was designed. – user207421 Apr 24 '20 at 03:35