Как предотвратить использование метода InputStream.readObject() для исключения EOFException?

Я сериализую объект и сохраняю его как файл на своем жестком диске. Когда я читаю его, только в некоторых случаях он бросает EOFException. После нескольких часов отладки я не могу найти проблему.

Вот мой код:

   public void serialize(MyClass myClass,String path) {
        FileOutputStream foStream = null;
        ObjectOutputStream ooStream = null;
        try {
            File file = new File(path);
            if (!file.exists()) {
                file.createNewFile();
            }
            foStream = new FileOutputStream(file);
            ooStream = new ObjectOutputStream(foStream);
            ooStream.writeObject(myClass);
        } catch (Throwable t) {
            log.error(t);
        } finally {
            if (ooStream != null) {
                try {
                    ooStream.flush();
                    ooStream.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }

        }
    }

Для получения объекта:

  public MyClass deSerialize(String path) {
        MyClass myClass=null;
        FileInputStream fiStream = null;
        ObjectInputStream oiStream = null;
        String errorMessage = "";
        try {
            File file = new File(path);
            if (!file.exists()) {
                return null;
            }
            fiStream = new FileInputStream(path);
            oiStream = new ObjectInputStream(fiStream);
            Object o = oiStream.readObject();
            myClass = (MyClass) o;
        } catch (Throwable t) {
            log.warn(t);
        } finally {
            if (oiStream != null) {
                try {
                    oiStream.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
        return myClass;
    }

StackTrace:

java.io.EOFException при java.io.ObjectInputStream $BlockDataInputStream.peekByte(ObjectInputStream.java:2498)   в java.io.ObjectInputStream.readObject0 (ObjectInputStream.java:1273)   в java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)   в java.util.LinkedList.readObject(LinkedList.java:776) в sun.reflect.GeneratedMethodAccessor583.invoke(Неизвестный источник) в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)   в java.lang.reflect.Method.invoke(Method.java:585) в java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:946)   в java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1809)   в java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)   в java.io.ObjectInputStream.readObject0 (ObjectInputStream.java:1305)   в java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1908)   в java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1832)   в java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)   в java.io.ObjectInputStream.readObject0 (ObjectInputStream.java:1305)   в java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)

Вопрос: Мой сериализованный объект теперь поврежден, и теперь это мусор?
Поскольку этот объект отвечает за отображение пользовательского интерфейса, который был сохранен пользователем. Если пользователь регистрируется в нем, он должен отображать ранее сохраненное состояние пользовательского интерфейса. Однако для некоторых пользователей файл нельзя десериализовать.

Ответ 1

EOFException означает, что вы пытаетесь прочитать за конец файла. Обычно у вас нет никакого способа узнать, есть ли еще больше объектов для чтения, кроме как попробовать, поэтому вы не должны рассматривать EOFException как проблему в первую очередь. Если он брошен в ситуации, когда, по вашему мнению, вы знаете, что в файле больше объектов, например. когда вы префиксный объект подсчитывает файл, это указывает на проблему с кодом, который написал файл, или на возможное повреждение самого файла. Другим примером является файл с нулевой длиной, который не должен быть нулевой длины. Какая бы проблема ни была, она не может быть решена конечным концом чтения, уже слишком поздно.

Ответ 2

Я не вижу проблемы с записью и чтением файла.

Поэтому я думаю, что проблема в уровне файлов. Например:

  • вы можете писать один файл и читать другой, или
  • вы можете прочитать файл перед завершением записи файла или
  • что-то другое может быть скреплено файлом между запуском вашего кода записи и чтением кода.

Я предлагаю вам добавить некоторый трассировочный код, который использует File.length(), чтобы узнать размер файла после его написания и перед его чтением.


Несколько других возможностей:

  • код писателя и читателя использует разные версии MyClass (или зависимого класса) с несовместимыми представлениями и одинаковыми значениями serialVersionId или

  • вы можете использовать пользовательские методы readObject и writeObject, которые несовместимы.

Ответ 3

В моем случае исключение EOF было решено, гарантируя, что чтение и запись в файл были потокобезопасными. Как и Стивен С ответил выше, если вы попытаетесь записать файл, который вы также пытаетесь прочитать, скажем, из другого потока, вы можете наступить на ObjectInputStream, который в этом случае собирается выбросить исключение EOF.