1

For my application I want to use a Map to act as a database. To save and load a map, I am writing/reading it to/from database.ser using this 2 methods:

private synchronized void saveDB() {
    try {
        fileOut = new FileOutputStream(db);
        out = new ObjectOutputStream(fileOut);
        out.writeObject(accounts);
        fileOut.close();
        out.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

@SuppressWarnings("unchecked")
private void loadDB() {
    try {
        fileIn = new FileInputStream(db);
        in = new ObjectInputStream(fileIn); // that is where error is produced if fileIn is empty
        accounts = (Map<String, Client>) in.readObject();
        in.close();
        fileIn.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

I want to load into Map when application starts, so I invoke method in constructor like this:

protected DriveatorImpl() {
    accounts = new ConcurrentHashMap<String, Client>();
    db = new File("C:/Users/eduar/git/Multy-Threaded-Bank-System/Bank-Services/database.ser"); 
// also, any suggestions how can I make path to a file more flexible in case I want to run Server side of an app on different machine?
     if (!db.exists()) {
        try {
            db.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
     }
    loadDB(); // loads database when server start 
}

I am aware of what causing an error, but I don't know what should I change in my design to avoid ObjectInputStream constructor receiving empty stream! Any suggestions on what I can do differently?

Edit: I want to note that in fresh application run database.ser is empty since there was no entries made into Map yet.

Thank You!

GarRudo
  • 158
  • 1
  • 10

2 Answers2

0

First why the EOFExcpetion occur?

  1. There are no contents in file or file is empty and you tried to read file.

Some code change and it worked for me.

@SuppressWarnings("unchecked")
private void loadDB() {
    try {
        if (db.length() <= 0) {
            // if statement evaluates to true even if file doesn't exists
            saveDB(); // save to a file an empty map
                      // if file doesn't exist, it creates a new one 
                      // call loadDB inside constructor

        }
        FileInputStream fileIn = new FileInputStream(db);
        ObjectInputStream in = new ObjectInputStream(fileIn); // that is where error is produced if fileIn is empty
        in.readObject();
        in.close();
        fileIn.close();
        System.out.println(accounts);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
Community
  • 1
  • 1
Gopinath Langote
  • 311
  • 4
  • 10
  • I can't make head or tail of #2, and the second bullet point is equally meaningless. Your 'another way' is exactly the same as your original way of checking for emptiness. – user207421 Jan 13 '17 at 09:19
  • I think checking for empty file and returning from method is exactly what I needed! I am calling saveDB() in methods where I am putting or modifying values in map to insure all data is saved in case server crashes. I think I understand now why calling saveDB() method in constructor before loadDB() would work. It writes to a file an empty map, but still some bytes going through the stream. Only problem is, if I have some values already stored in Map and I save it to a file, subsequent instantiation of a class will overwrite file with empty map and all data will be lost. Thank you for your help! – GarRudo Jan 13 '17 at 09:24
  • You are welcome. Please try to avoid the duplicate question as @EJP mentioned. It will help to avoid mess up. Thank you. – Gopinath Langote Jan 13 '17 at 10:06
  • I don't agree with @EJP that question is duplicated. Last question was about path to a file and File Not Found Exception. An additional error was revealed during a review that cause EOFExcpetion and has to do with empty stream being passed to an ObjectInputStream constructor. I think this question requires individual attention. – GarRudo Jan 13 '17 at 10:15
  • @GarRudo Please tick to the answer I have submitted for your problem so that, other people can see that, this solved your issue. Thank you. – Gopinath Langote Jan 13 '17 at 12:05
  • Fixed. Thank you. – GarRudo Jan 14 '17 at 18:43
0

Get rid of the file.exists()/file.createNewFile() crap. All it is doing for you is masking the original FileNotFoundException problem, and turning into a thoroughly predictable EOFException because of trying to construct an ObjectInputStream around an empty stream. Handle the original problem. Don't just move it, or turn it into something else.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I understand now when read your comment to original post. This would be a graceful solution I need. Thank you. – GarRudo Jan 13 '17 at 09:48