2

A few days ago I asked a question about reading from file until the input has finished. I've received some responses which I studied, but I have one question somehow relevant to the topic: why do I have to use some additional tests, "finally" clause and another try-catch there instead of just:

DataInputStream reading = null;
try{
        reading = new DataInputStream(new FileInputStream("tes.t"));
        while(true)
        {
            System.out.println(reading.readInt());
            System.out.println(reading.readDouble());
        }
        }catch(IOException xxx){System.err.println("Error: " + reading.getMessage());}
         catch(EOFException xxx){reading.close();}

Why is this not enough? I mean - as soon as we reach EOF, we'll have an exception. Otherwise, we catch the exception and print the error message. Why do we need additional tests? What's wrong with this approach?

EDIT: OK, I now understand why it's a bad thing. But what about if I made the code like this:

DataInputStream reading = null;
try{
        reading = new DataInputStream(new FileInputStream("tes.t"));
        while(reading.available()!=0)
        {
            System.out.println(reading.readInt());
            System.out.println(reading.readDouble());
        }
        }catch(EOFException xxx){}
         catch(IOException xxx){System.err.println("Error: " + reading.getMessage());}

Is checking the value of reading.available() a better test for the input end or just as bad?

Straightfw
  • 1,995
  • 2
  • 22
  • 36
  • 2
    Your reading will never be closed since IOException is on the top of EOFException in Exception heirarchy. It should actually give you some compilation error. – Jimmy Nov 09 '12 at 19:26
  • Oh, that's right. My bad, the code was added in the post editor, not compiled or tested - thank you :) – Straightfw Nov 09 '12 at 19:36
  • You want to wait a fair amount of time before you check an accepted answer. You will get a lot more eyes and time for others to consider your question. Even thought you might find an adequate and even good answer early on, the site as a resource will benefit from additional answers. – Captain Giraffe Nov 09 '12 at 19:41
  • I see. I unaccepted the answer and should nothing better appear, I'll surely reaccept it :) – Straightfw Nov 09 '12 at 19:44

2 Answers2

3

It's not elegant to control your execution flow with exceptions. EOF is a normal situation while reading a file so it should be handled in other way.

The more elegant code would be:

byte[] buf = new byte[8192];
int nread;
while ((nread = is.read(buf)) >= 0) {
  // process the first `nread` bytes of `buf`
}

source: Unknown buffer size to be read from a DataInputStream in java

Here is you can find very good explaintation why you shouldn't control flow with exceptions: Why not use exceptions as regular flow of control?

Community
  • 1
  • 1
Adam Sznajder
  • 8,642
  • 3
  • 32
  • 60
  • I don't know if that applies here, OP is utilizing a `File` and it would not be a random stream, but it would be a very fixed amount of data to process. i.e. the length of the file. However, as a general (non-file oriented approach) agree that the above is valid. – Woot4Moo Nov 09 '12 at 19:23
  • 2
    Elegant could be debated, IMO exceptions can be used to create very elegant flow control. It is not however; efficient, idiomatic, common, practical nor readable (in Java) to do so. – Captain Giraffe Nov 09 '12 at 19:26
  • @CaptainGiraffe - I see, thank you :) Also, I'll surely give what you added after the edit a read. Thanks! – Straightfw Nov 09 '12 at 19:37
  • Also worth noting in this context is that there has been quite a few google talks dedicated to using polymorphism as(instead of) flow control. Interesting talks but I have a hard time seeing them becoming idiomatic anytime soon. – Captain Giraffe Nov 09 '12 at 19:37
  • When an API throws EOFException to indicate end of file, you don't have any choice but to catch it and react accordingly, so your first sentence is meaningless in this context. It is meaningless in any context actually, as exceptions *are* flow control statements. Reading the data twice just to avoid catching EOFException as you appear to be suggesting is positively perverse. – user207421 Nov 09 '12 at 21:05
  • You didn't understand me right. I said that you shouldn't use an exception as a reaction to normal situation. Every file has EOF so it's more elegant (readable etc.) to handle it in a loop condition than use exceptions. What is more not all classes throw EOFException. If I sounded to you not accurately than sorry - I'm not a native English speaker and sometimes my posts might look imprecise. – Adam Sznajder Nov 09 '12 at 21:13
  • I understand perfectly. You have several misunderstandings. You think that exceptions aren't a control flow mechanism when they are. You think that EOF is normal when reading a file, when what is normal is getting data, and EOF is the exceptional condition that tells you to stop. You think that reading data twice is more elegant than reading it once. You think that bypassing the API provided is more elegant than using it as designed. You think I said that all classes throw EOFException when I said no such thing. – user207421 Nov 09 '12 at 21:18
0

You need the finally clause to close resources. It is possible to not hit an EOF and that finally block still needs to execute. Further the above code is atrocious and should never be used in a production system, especially since you know the condition when the file is over. Ideally the other people that reviewed this have made the same statements. Treating exceptions as "normal" program execution flow is the least favorable approach to software engineering problems.

Woot4Moo
  • 22,887
  • 13
  • 86
  • 143