views:

577

answers:

4

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++;
    }
+2  A: 

readObject() doesn't return null at EOF. You could catch the EOFException and interpret it as EOF, but this would fail to detect 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.

erickson
If the last 'object' written to the stream was `null`, then you would read the `null` reference fine. It's normal for `null`s 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.
Tom Hawtin - tackline
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
@EJP No really, don't go around catch `EOFException` to terminate loops.
Tom Hawtin - tackline
A pointless comment. You don't have any choice except in the case of InputStream.read(), Reader.read(), and the various readLine() methods.
EJP
A: 

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.

Manuel Darveau
'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.
EJP
+1  A: 

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)

Tom Hawtin - tackline
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
@EJP You what?! Why wouldn't a `null` be written if a `null` was expected to be read?
Tom Hawtin - tackline
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.
EJP
A: 

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

EJP
-1 In my opinion, this is dangerous programming. Just don't do it.
Tom Hawtin - tackline
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.
EJP
@EJP Oh come off it. Catching an `EOFException` is hopeless. If you can't see that, then I don't think there is any way to help you.
Tom Hawtin - tackline
Tom1. 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.
EJP