如何防止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; } 

堆栈跟踪:

java.io.ObjectInputStream中的java.io.EOFException $ java.io.ObjectInputStream.readObject(ObjectInputStream.java:1273)java.io.ObjectInputStream.readObject(ObjectInputStream.java)中的java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1273) 348)在java.util.LinkedList.readObject(LinkedList.java:776)at sun.reflect.GeneratedMethodAccessor583.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect .Method.invoke(Method.java:585)位于java.io.ObjectInputStream.readSerial上的java.io.ObjectInputStream.readSerial(ObjectInputStream.java:1809)中的java.io.Object.StreamClass.invokeReadObject(ObjectStreamClass.java:946) ObjectInputStream.java:1719)java.io.ObjectInputStream.readSerial上的java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)java.io.ObjectInputStream.readSerial上的java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1908)。(ObjectInputStream.java:1832) )在java.io.ObjectInputStream.readOrdinaryObject( ObjectInputStream.java:1719)java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)

问题:我的序列化对象现在已损坏,现在是垃圾吗?
因为此对象负责呈现由用户保存的UI。 如果用户登录它应该呈现以前保存的UI状态。 但是对于某些用户,该文件无法反序列化。

EOFException意味着您尝试读取文件末尾。 通常你没有任何方法可以知道除了尝试之外还有更多的对象需要阅读,因此你不应该首先将EOFException视为一个问题。 如果它是在您认为您知道文件中有更多对象的情况下抛出的,例如,当您为文件添加了对象计数前缀时,则表示编写该文件的代码存在问题,或者文件可能损坏本身。 另一个例子是零长度文件,它不应该是零长度。 无论问题是什么,阅读结束都无法解决,已经为时已晚。

我看不到写入和读取文件的任何问题。

所以我最好的猜测是问题出在文件级别。 例如:

  • 你可能正在写一个文件并阅读另一个文件,或者
  • 您可以在文件写入完成之前读取文件,或者
  • 在编写代码的运行和读取代码之间,其他东西可能会破坏文件。

我建议你添加一些使用File.length()的跟踪代码,以便在你编写之后和阅读之前找出文件大小。


其他几种可能性:

  • 编写器和读者代码使用不同版本的MyClass (或依赖类),具有不兼容的表示和相同的serialVersionId值,或者

  • 您可能正在使用不兼容的自定义readObjectwriteObject方法。

在我的例子中,通过确保对文件的读取和写入是线程安全的来解决EOFexception。 就像Stephen C上面回答的那样,如果你试图写一个你也试图从另一个线程中读取的文件,你可能会踩到ObjectInputStream,在这种情况下会抛出EOF Exception。