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++;
}
I am trying to read the number of line in a binary file using readObject, but I get IOException EOF. Am I doing this the right way?
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++;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
readObject()
在 EOF 处不返回null
。您可以捕获 EOFException 并将其解释为 EOF,但这无法区分正常的 EOF 和已被截断的文件。更好的方法是使用一些元数据。也就是说,您应该将计数存储在某处,而不是询问
ObjectInput
流中有多少个对象。例如,您可以创建一个记录计数和其他元数据的元数据类,并将实例存储为每个文件中的第一个对象。或者您可以创建一个特殊的 EOF 标记类并将一个实例存储为每个文件中的最后一个对象。readObject()
doesn't returnnull
at EOF. You could catch theEOFException
and interpret it as EOF, but this would fail to distinguish a normal EOF from a file that has been truncated.A better approach would be to use some meta-data. That is, rather than asking the
ObjectInput
how many objects are in the stream, you should store the count somewhere. For example, you could create a meta-data class that records the count and other meta-data and store an instance as the first object in each file. Or you could create a special EOF marker class and store an instance as the last object in each file.我今天也遇到了同样的问题。尽管这个问题很老了,但问题仍然存在,并且没有提供干净的解决方案。应避免忽略 EOFException ,因为当某些对象未正确保存时可能会抛出该异常。写入 null 显然会阻止您将 null 值用于任何其他目的。最后,在对象流上使用
available()
始终返回零,因为对象的数量未知。我的解决方案非常简单。
ObjectInputStream
只是其他一些流的包装,例如 FileInputStream。尽管ObjectInputStream.available ()
返回零,但FileInputStream.available将返回一些值。I had the same problem today. Although the question is quite old, the problem remains and there was no clean solution provided. Ignoring
EOFException
should be avoided as it may be thrown when some object was not saved correctly. Writing null obviously prevents you from using null values for any other purposes. Finally usingavailable()
on the objects stream always returns zero, as the number of objects is unknown.My solution is quite simple.
ObjectInputStream
is just a wrapper for some other stream, such as FileInputStream. AlthoughObjectInputStream.available ()
returns zero, the FileInputStream.available will return some value.不可以。捕获
EOFException
并使用它来终止循环。No. Catch
EOFException
and use that to terminate the loop.如果您在文件末尾写入一个空对象,那么当您读回它时,您将得到一个空值并可以终止循环。
只需添加:
out.writeObject(null);
当您序列化数据时。
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.
奇怪的是 API 没有为此提供更优雅的解决方案。我想 EOFException 会起作用,但我总是被鼓励将异常视为意外事件,而在这里您通常会期望对象流结束。
我尝试通过编写一种“标记”对象来表示对象流的结束来解决此问题:
然后在读取对象的代码中,我在对象读取中检查了此 EOF 对象环形。
It's curious that the API doesn't supply a more elegant solution to this. I guess the
EOFException
would work but I've always been encouraged to see exceptions as unexpected events whereas here you would often expect the object stream to come to an end.I tried to work around this by writing a kind of "marker" object to signify the end of the object stream:
Then in the code reading the object i checked for this EOF object in the object reading loop.
不,您需要知道二进制文件中有多少个对象。您可以在文件开头写入对象的数量(例如使用 writeInt)并在加载时读取它。
另一种选择是调用 ois.available() 并循环直到返回 0。但是,我不确定这是否 100% 确定。
No, you need to know how many objects there is in the binary file. You could write the number of objects at the beginning of the file (using writeInt for example) and read it while loading it.
Another option is to call ois.available() and loop until it returns 0. However, I am not sure if this is 100% sure.
看起来问题出在您写出的数据上。假设数据按照这段代码的预期写入,应该不会有问题。
(我看到您正在读取
String
。此ObectInputStream
不适用于读取文本文件。使用InputStreamReader
和BufferedReader.readLine<同样,如果您使用
DataOutputSteam.writeUTF
写入文件,请使用DataInputStream.readUTF
读取它。It looks like the problem is with the data that you wrote out. Assuming the data is written as expected by this code, there shouldn't be a problem.
(I see you are reading
String
s. ThisObectInputStream
isn't for reading text files. UseInputStreamReader
andBufferedReader.readLine
for that. Similarly if you have written the file withDataOutputSteam.writeUTF
, read it withDataInputStream.readUTF
)ObjectInputStream 的 available 方法不能用于终止循环,因为即使文件中有要读取的对象,它也会返回 0。将 null 写入文件似乎也不是一个好的解决方案,因为对象可以为 null,然后这将被解释为文件结尾。我认为捕获 EOFException 来终止循环是一种更好的做法,因为如果发生 EOFException (因为到达文件末尾或其他原因),则无论如何都必须终止循环。
The available method of ObjectInputStream cannot used to terminate the loop as it returns 0 even if there are objects to be read in a file. Writing a null to a file doen't seem to be a good solution either since objects can be null which then would be interpreted as the end of file. I think catching the EOFException to terminate the loops is a better practice since if EOFException occurs(either because you reached the end of the file or some other reason), you have to terminate the loop anyway.
结束循环的最佳方法是在末尾添加一个空对象。 while读取空对象可以作为退出循环的边界条件。捕获 EOFException 也可以解决目的,但需要几米
The best possible way to end the loop could be done by adding a null object at the end. While reading the null object can be used as a boundary condition to exit the loop. Catching the EOFException also solves the purpose but it takes few m