Java FileInputStream ObjectInputStream到达文件结尾EOF

我试图使用readObject读取二进制文件中的行数,但我得到IOException EOF。 我这样做是对的吗?

FileInputStream istream = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(istream); /** calculate number of items **/ int line_count = 0; while( (String)ois.readObject() != null){ line_count++; } 

readObject()在EOF时不返回null 。 您可以捕获EOFException并将其解释为EOF,但这将无法检测到将正常EOF与已截断的文件区分开来。

更好的方法是使用一些元数据。 也就是说,您应该将计数存储在某处,而不是要求ObjectInput在流中有多少个对象。 例如,您可以创建一个元数据类来记录计数和其他元数据,并将实例存储为每个文件中的第一个对象。 或者,您可以创建一个特殊的EOF标记类,并将实例存储为每个文件中的最后一个对象。

我今天遇到了同样的问题。 虽然这个问题很老,但问题仍然存在,并且没有提供干净的解决方案。 应避免忽略EOFException因为在某些对象未正确保存时可能会抛出它。 写入null显然会阻止您将null值用于任何其他目的。 最后,对象流上的available()总是返回零,因为对象的数量是未知的。

我的解决方案非常简单。 ObjectInputStream只是其他一些流的包装器,例如FileInputStream。 虽然ObjectInputStream.available ()返回零,但FileInputStream.available将返回一些值。

  FileInputStream istream = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(istream); /** calculate number of items **/ int line_count = 0; while( istream.available() > 0) // check if the file stream is at the end { (String)ois.readObject(); // read from the object stream, // which wraps the file stream line_count++; } 

No. Catch EOFException并使用它来终止循环。

奇怪的是,API没有为此提供更优雅的解决方案。 我想EOFException会起作用,但我总是被鼓励将exception视为意外事件,而在这里你经常会期望对象流结束。

我尝试通过编写一种“标记”对象来表示对象流的结束:

 import java.io.Serializable; public enum ObjectStreamStatus implements Serializable { EOF } 

然后在代码中读取对象,我在对象读取循环中检查了这个EOF对象。

不,您需要知道二进制文件中有多少个对象。 您可以在文件开头写入对象的数量(例如使用writeInt)并在加载时读取它。

另一种选择是调用ois.available()并循环直到它返回0.但是,我不确定这是否100%肯定。

看起来问题在于你写的数据。 假设此代码按预期写入数据,则应该没有问题。

(我看到你正在阅读String s。这个ObectInputStream不是用于读取文本文件。请使用InputStreamReaderBufferedReader.readLine 。类似地,如果你用DataOutputSteam.writeUTF编写了文件,请用DataInputStream.readUTF读取它)

即使在文件中有要读取的对象,ObjectInputStream的可用方法也不能用于终止循环,因为它返回0。 将null写入文件似乎不是一个好的解决方案,因为对象可以为null,然后将其解释为文件的结尾。 我认为捕获EOFException以终止循环是一种更好的做法,因为如果发生EOFException(因为你到达文件末尾或其他原因),你必须终止循环。

如果在文件末尾写入一个空对象,当您将其读回时,您将获得一个空值并可以终止循环。

只需添加:out.writeObject(null);

当您序列化数据时。

结束循环的最佳方法可以通过在末尾添加空对象来完成。 读取null对象时可以用作边界条件来退出循环。 捕获EOFException也解决了目的,但需要几米