27

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++;
    }
1
  • I'm doing the same thing--but I'm tailing an active log. I would like it to wait until more data is there as long as the program is writing, but tell me when it's done writing. I'm not sure if there is any way to do this without catching the exception. (The tailing part works fine, it's just getting it to exit when it's done that's bugging me) Commented Jun 21, 2010 at 22:28

9 Answers 9

32

readObject() doesn't return null at EOF. You could catch the EOFException 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.

Sign up to request clarification or add additional context in comments.

5 Comments

If the last 'object' written to the stream was null, then you would read the null reference fine. It's normal for nulls to be a part of the serial form, and there is a special representation for it in the serial format. A null at the end, or some other sentinel, is much cleaner that a count.
Thanks I just wrote null after all the contents so signal where the end of the file was. It worked prefect.
But it doesn't accomplish that, unless you assume you've never written a null at any other point. The correct answer is to catch EOFException and use that to terminate the loop.
@EJP No really, don't go around catch EOFException to terminate loops.
A pointless comment. You don't have any choice except in the case of InputStream.read(), Reader.read(), and the various readLine() methods.
19

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 using available() 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. Although ObjectInputStream.available () returns zero, the FileInputStream.available will return some value.

   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++;
   }

4 Comments

This only works if ObjectInputStream doesn't do any buffering. Is this the case? The javadoc doesn't tell anything about this.
available() is not a valid test for end of stream. See the Javadoc.
how is this supposed to help? the one method call, ois.readObject(), which throws the error, will still be called in your example and thus throw an error. at least, it didn't work for me.. :/
To elaborate on what EJP has written, FileInputStream.available() gives a count of how many bytes are available to read only. This can be 0 for something as normal as IO input delay. Your code may start breaking unexpectedly.
6

No. Catch EOFException and use that to terminate the loop.

2 Comments

How exactly is it dangerous? Chapter and verse please. In any case as I have already said here, you don't have any alternative, unless you write a 'null' to the ObjectOutputStream, in which case you are removing all the other useful uses of that action.
Tom 1. Please stop waffling and answer the question. Tell us exactly what is 'dangerous' about this: catch (EOFException exc) { break; } 2. Please tell us how to read an entire ObjectInputStream without catching EOFException and without constraining the writer of that stream as to how to do it. You can't. It can't be done. EOFException is the only mechanism.
6

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.

2 Comments

I do not understand why this does not get more upvotes. Simple and works like a charm for me.
@ChristophHenkelmann Because it means you can't write a null anywhere else in the stream, and because you still have to handle `EOFException in case the writing application failed to finish writing the file.
1

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:

import java.io.Serializable;

public enum ObjectStreamStatus implements Serializable {
    EOF
}


Then in the code reading the object i checked for this EOF object in the object reading loop.

1 Comment

The API can't provide a 'more elegant solution than this'. An out of band result is required. An exception is the only possibility.
0

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.

1 Comment

'No, you need to know how many objects there is in the binary file'. No you don't. 'I am not sure if this is 100% sure.' It isn't. There's a specific statement in the Javadoc about that.
0

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 Strings. This ObectInputStream isn't for reading text files. Use InputStreamReader and BufferedReader.readLine for that. Similarly if you have written the file with DataOutputSteam.writeUTF, read it with DataInputStream.readUTF)

3 Comments

Incorrect. EOFException is normal, and unless he wrote a null there is no reason to terminate the loop at null so his loop is wrong.
@EJP You what?! Why wouldn't a null be written if a null was expected to be read?
That's exactly my point. If you want a null to be read, write a null. If you want EOFException to be caught, close the stream. These are two different actions. Conflating them serves no useful purpose.
0

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.

1 Comment

The available() method cannot be used for this purpose because that's not what it's for. See the Javadoc.
-1

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

2 Comments

you answer seems to be incomplete, the last sentence does not finish
And what you've written so far is incorrect, as it makes it impossible to write null in any other place.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.