我试图使用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++;
}
答案 0 :(得分:25)
readObject()
不会在EOF返回null
。您可以捕获EOFException
并将其解释为EOF,但这将无法检测到将正常EOF与已截断的文件区分开来。
更好的方法是使用一些元数据。也就是说,不是要求ObjectInput
流中有多少个对象,而是应该将计数存储在某处。例如,您可以创建一个元数据类来记录计数和其他元数据,并将实例存储为每个文件中的第一个对象。或者,您可以创建一个特殊的EOF标记类,并将实例存储为每个文件中的最后一个对象。
答案 1 :(得分:19)
我今天遇到了同样的问题。虽然这个问题很老,但问题仍然存在,并且没有提供干净的解决方案。应该避免忽略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++;
}
答案 2 :(得分:6)
没有。捕获EOFException
并使用它来终止循环。
答案 3 :(得分:2)
如果你在文件的末尾写一个空对象,当你读回它时,你会得到一个空值,并可以终止你的循环。
添加: out.writeObject(NULL);
序列化数据时。
答案 4 :(得分:1)
奇怪的是API没有为此提供更优雅的解决方案。我想EOFException
会起作用但我总是被鼓励将异常视为意外事件,而在这里你经常会期望对象流结束。
我尝试通过编写一种“标记”对象来表示对象流的结束:
import java.io.Serializable;
public enum ObjectStreamStatus implements Serializable {
EOF
}
然后在代码中读取对象,我在对象读取循环中检查了这个EOF对象。
答案 5 :(得分:0)
不,您需要知道二进制文件中有多少个对象。您可以在文件开头写入对象的数量(例如使用writeInt)并在加载时读取它。
另一种选择是调用ois.available()并循环直到它返回0.但是,我不确定这是否100%确定。
答案 6 :(得分:0)
看起来问题在于你写的数据。假设数据是按照此代码的预期编写的,那么应该没有问题。
(我看到您正在阅读String
s。此ObectInputStream
不是用于阅读文本文件。请使用InputStreamReader
和BufferedReader.readLine
。如果您已经写过包含DataOutputSteam.writeUTF
的文件,请使用DataInputStream.readUTF
)
答案 7 :(得分:0)
ObjectInputStream的可用方法不能用于终止循环,因为即使在文件中有要读取的对象,它也会返回0。将null写入文件似乎不是一个好的解决方案,因为对象可以为null,然后将其解释为文件的结尾。我认为捕获EOFException以终止循环是一种更好的做法,因为如果发生EOFException(因为你到达了文件的末尾或其他原因),你必须终止循环。
答案 8 :(得分:-1)
结束循环的最佳方法可以通过在末尾添加一个空对象来完成。读取null对象时可以用作边界条件来退出循环。捕获EOFException也解决了目的,但需要很少m