25

我正在尝试使用 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++;
    }
4

9 回答 9

31

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

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

于 2010-04-12T23:59:13.510 回答
18

我今天遇到了同样的问题。尽管这个问题已经很老了,但问题仍然存在,并且没有提供干净的解决方案。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++;
   }
于 2012-11-13T14:29:12.107 回答
6

不。抓住EOFException并使用它来终止循环。

于 2010-04-13T07:37:11.823 回答
4

If you write a null object at the end of the file, when you read it back you will get a null value and can terminate your loop.

Just add: out.writeObject(null);

when you serialize the data.

于 2018-04-11T15:24:46.523 回答
1

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

我试图通过编写一种“标记”对象来表示对象流的结束来解决这个问题:

import java.io.Serializable;

public enum ObjectStreamStatus implements Serializable {
    EOF
}


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

于 2013-12-07T18:09:51.850 回答
0

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

于 2012-08-14T13:34:26.030 回答
0

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

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

于 2010-04-13T00:02:56.933 回答
0

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

(我看到您正在阅读Strings。这ObectInputStream不是用于阅读文本文件。使用InputStreamReaderand BufferedReader.readLine。同样,如果您使用 编写文件DataOutputSteam.writeUTF,请使用 阅读DataInputStream.readUTF

于 2010-04-13T00:32:22.113 回答
-1

结束循环的最佳方法是在末尾添加一个空对象。同时读取空对象可以作为边界条件退出循环。捕捉 EOFException 也解决了目的,但它需要几个 m

于 2011-11-03T07:27:42.490 回答