Обходной путь java.io.EOFException вызывается ObjectInputStream

Для своего приложения я хочу использовать карту в качестве базы данных. Чтобы сохранить и загрузить карту, я пишу/читаю ее в/из database.ser, используя эти 2 метода:

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();
    }
}

Я хочу загрузить карту при запуске приложения, поэтому я вызываю метод в конструкторе следующим образом:

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 
}

Я знаю, что вызывает ошибку, но я не знаю, что мне следует изменить в моем дизайне, чтобы конструктор ObjectInputStream не получал пустой поток! Любые предложения о том, что я могу сделать по-другому?

Изменить: я хочу отметить, что в новом запуске приложения database.ser пуст, поскольку в карту еще не было внесено записей.

Спасибо!


person GarRudo    schedule 13.01.2017    source источник


Ответы (2)


Во-первых, почему возникает EOFExcpetion?

  1. В файле нет содержимого или файл пуст, и вы попытались прочитать файл.

Некоторое изменение кода, и это сработало для меня.

@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();
    }
}
person Gopinath Langote    schedule 13.01.2017
comment
Я не могу понять голову или хвост № 2, и второй пункт в списке столь же бессмысленен. Ваш «другой способ» точно такой же, как ваш первоначальный способ проверки на пустоту. - person user207421; 13.01.2017
comment
Я думаю, что проверка на наличие пустого файла и возврат из метода — это именно то, что мне нужно! Я вызываю saveDB() в методах, в которых я помещаю или изменяю значения на карте, чтобы гарантировать сохранение всех данных в случае сбоя сервера. Думаю, теперь я понимаю, почему вызов метода saveDB() в конструкторе до того, как loadDB() будет работать. Он записывает в файл пустую карту, но все же какие-то байты идут через поток. Единственная проблема заключается в том, что если у меня уже есть некоторые значения, сохраненные на карте, и я сохраняю их в файл, последующее создание экземпляра класса перезапишет файл пустой картой, и все данные будут потеряны. Спасибо за помощь! - person GarRudo; 13.01.2017
comment
Пожалуйста. Пожалуйста, постарайтесь избежать дублирования вопроса, как упоминалось в @EJP. Это поможет избежать путаницы. Спасибо. - person Gopinath Langote; 13.01.2017
comment
Я не согласен с @EJP, что вопрос дублируется. Последний вопрос был о пути к файлу и исключении «Файл не найден». В ходе проверки была обнаружена дополнительная ошибка, вызывающая EOFExcpetion и связанная с передачей пустого потока в конструктор ObjectInputStream. Думаю, этот вопрос требует отдельного внимания. - person GarRudo; 13.01.2017
comment
@GarRudo Пожалуйста, отметьте ответ, который я отправил для вашей проблемы, чтобы другие люди могли видеть, что это решило вашу проблему. Спасибо. - person Gopinath Langote; 13.01.2017
comment
Фиксированный. Спасибо. - person GarRudo; 14.01.2017

Избавьтесь от file.exists()/file.createNewFile() дерьма. Все, что он делает для вас, это маскирует первоначальную проблему FileNotFoundException и превращается в полностью предсказуемую проблему EOFException из-за попытки построить ObjectInputStream вокруг пустого потока. Решите исходную проблему. Не просто перемещайте его или превращайте во что-то другое.

person user207421    schedule 13.01.2017
comment
Теперь я понимаю, когда прочитал ваш комментарий к исходному сообщению. Это было бы изящным решением, которое мне нужно. Спасибо. - person GarRudo; 13.01.2017