Try Catch logic error with file i/o in Java
So, I’ve been trying to learn java from various sources, I’ve been learning for about 2 years now. So far everything has been going smoothly, i haven’t had to post on stackoverflow for a while. Recently I’ve been trying to figure out how to create and read files with java. I can do both of those things in separate apps, but when i try to do both it doesn’t always work. What i want to happen: I want my program to create data.txt , then I want it to read the data and produce an error log on error.txt . What happens: The data.txt file gets created as expected, but nothing is written to the error.txt file. I’m having trouble grasping the try/catch block and how exactly it works. Anyone got any ideas? even just some advice would be appreciated. Thanks!
import java.io.*; import java.util.Scanner; public class dataReader < public static void main(String args[]) throws Exception < File fileName; fileName = new File("data.txt"); PrintWriter outputFile; outputFile = new PrintWriter(fileName); File errorFile; errorFile = new File("errors.txt"); PrintWriter outputErrorFile; outputErrorFile = new PrintWriter(errorFile); Scanner inputFile; int recordNumber = 0; String inputData; outputFile.println(77); outputFile.println("Fred"); outputFile.println(92); outputFile.println("Wilma"); outputFile.println(89.9); outputFile.println("Barney"); outputFile.println(42); outputFile.println("BettyS"); inputFile = new Scanner(fileName); while (inputFile.hasNext()) < recordNumber++; try < inputData = inputFile.nextLine(); if (Integer.parseInt(inputData) < 50) < outputErrorFile.println(recordNumber + ", " + inputData + ", is less than 50."); >else if (Integer.parseInt(inputData) > 90) < outputErrorFile.println(recordNumber + ", " + inputData + ", is less than 50."); >> catch (Exception e) < outputErrorFile.println(recordNumber + ", That's not an integer."); >> outputFile.close(); outputErrorFile.close(); System.out.println("Program terminated."); > >
How can I catch all exceptions thrown through reading / writing a file?
In Java, is there any way to get (catch) all exceptions instead of catching the exceptions individually?
7 Answers 7
If you want, you can add throws clauses to your methods. Then you don’t have to catch checked methods right away. That way, you can catch the exceptions later (perhaps at the same time as other exceptions ).
public void someMethode() throws SomeCheckedException < // code >
Then later you can deal with the exceptions if you don’t wanna deal with them in that method.
To catch all exceptions some block of code may throw you can do: (This will also catch Exceptions you wrote yourself)
The reason that works is because Exception is the base class for all exceptions. Thus any exception that may get thrown is an Exception (Uppercase ‘E’).
If you want to handle your own exceptions first simply add a catch block before the generic Exception one.
try< >catch(MyOwnException me)< >catch(Exception e)
While I agree it’s not good style to catch a raw Exception, there are ways of handling exceptions which provide for superior logging, and the ability to handle the unexpected. Since you are in an exceptional state, you are probably more interested in getting good information than in response time, so instanceof performance shouldn’t be a big hit.
try < // IO code >catch (Exception e) < if(e instanceof IOException)< // handle this exception type >else if (e instanceof AnotherExceptionType) < //handle this one >else < // We didn't expect this one. What could it be? Let's log it, and let it bubble up the hierarchy. throw e; >>
However, this doesn’t take into consideration the fact that IO can also throw Errors. Errors are not Exceptions. Errors are a under a different inheritance hierarchy than Exceptions, though both share the base class Throwable. Since IO can throw Errors, you may want to go so far as to catch Throwable
try < // IO code >catch (Throwable t) < if(t instanceof Exception)< if(t instanceof IOException)< // handle this exception type >else if (t instanceof AnotherExceptionType) < //handle this one >else < // We didn't expect this Exception. What could it be? Let's log it, and let it bubble up the hierarchy. >> else if (t instanceof Error) < if(t instanceof IOError)< // handle this Error >else if (t instanceof AnotherError) < //handle different Error >else < // We didn't expect this Error. What could it be? Let's log it, and let it bubble up the hierarchy. >> else < // This should never be reached, unless you have subclassed Throwable for your own purposes. throw t; >>
How to properly catch exceptions with java file I/O [duplicate]
I’m trying to become familiar with file I/O in Java. I started off by getting a lot of errors when compiling, such as error: unreported exception IOException; must be caught or declared to be thrown . So I made some changes to the code and ended up with:
public static void main(String[] args)< FileInputStream in = null; FileOutputStream out = null; String content = "hello"; byte[] contentBytes = content.getBytes(); try< out = new FileOutputStream("output.txt"); out.write(contentBytes); >catch(IOException e)< >catch(FileNotFoundException e) < >finally < if (out != null) out.close(); >>
FileIO.java:16: error: exception FileNotFoundException has already been caught >catch(FileNotFoundException e)< ^ FileIO.java:21: error: unreported exception IOException; must be caught or declared to be thrown out.close(); ^ 2 errors
- Where did I "already catch" FileNotFoundException ?
- Because of the second error, do I need to put another try and catch statement in the finally clause to catch IOException ? That seems messy and over-complicated. Am I doing something else wrong? And why doesn't java let me do what I want without forcing me to catch exceptions?
public static void main(String[] args)< FileOutputStream out = null; String content = "hello"; byte[] contentBytes = content.getBytes(); try< out = new FileOutputStream("output.txt"); out.write(contentBytes); >catch(FileNotFoundException e)< >catch(IOException e) < >finally < if (out != null) out.close(); >>
FileIO.java:20: error: unreported exception IOException; must be caught or declared to be thrown out.close(); ^ 1 error
Your other question is probably answered here: Java catching exceptions and subclases. Although I'd recommend sticking to one question per post to get better answers for each issue and make the post more useful to others.
@Ravi The post is currently asking two distinct questions - there probably needs to be a rather significant edit to the question body (by the author) to justify a title that focuses on only one of them (although the answers would make such an edit problematic).
@Ravi Pretty much, if you want. Although I don't mind much because I think the question should be closed as too broad or a duplicate.
@Dukeling I rolled back to old change. I thought to make title more meaningful so that people can search easily. But, I agree with your point. 🙂
5 Answers 5
Where did I "already catch" FileNotFoundException?
FileNotFoundException extends IOException , which means IOException can catch FileNotFoundException exception. So, there is no point of FileNotFoundException after it.
Just reverse the order, to resolve this issue.
>catch(FileNotFoundException e)< >catch(IOException e)
Also, don't leave catch block blank, use them to display appropriate message, else you won't have any clue, if you got any exception.
second error, do I need to put another try and catch statement in the finally clause to catch IOException?
Yes. But, I would suggest to use try-with-resource it will take care of closing resource at the end.
As said, you should use try-with-resource instead
try (FileOutputStream out = new FileOutputStream("people.bin");) < out.write(contentBytes); >catch(FileNotFoundException e) < >catch(IOException e)
@Sahand I have noticed many times, you seems to have habit of downvoting immediately. You should have patience and ask back and forth question.
I am not really sure how the compiler let you the code. Could you please try the below code. I dont have any error when i run it.
Answer to the first question is :
Either remove FileNotFoundException line or put it above IOexception.
Answer to the second question is :
if you think that is messy, you can just duck the exception by using Throws i.e. throws IOException next to main(String[] args).
Java(compiler) pushes you to catch or declare your exceptions(using throws) because, the main purpose of Exceptions in java is not running into errors when the code is run. When an exception happens in the finally block, it leads to error and it ultimately impacts your application at run time. Have to very careful when you are closing stuff in Finally block. If you think, the code looks messy, then you can use Throws key word which solves your concern.
public static void main(String[] args)< FileInputStream in = null; FileOutputStream out = null; String content = "hello"; byte[] contentBytes = content.getBytes(); try< out = new FileOutputStream("output.txt"); out.write(contentBytes); >catch(IOException e) < >finally< if (out != null)< try< out.close(); >catch(IOException e) < >> > >
Java try/catch/finally best practices while acquiring/closing resources
The problem is that Netbeans is telling me the resource.close() lines throw an IOException and therefore must either be caught or declared. It also is complaining that oos and fos might not yet be initialized (despite the null checks). This seems a little strange, seeing as how the whole point is to stop the IOException right there. My knee-jerk fix is to do this:
> finally < try < if (oos != null) oos.close(); if (fos != null) fos.close(); >catch (IOException ex) < >>
But deep down this bothers me and feels dirty. I come from a C# background, where I would simply take advantage of a using block, so I am unsure of what the "right" way is to handle this. What is the right way to handle this problem?
Note that your knee-jerk fix won't close fos when oos.close() throws IOException . Each needs to go in its own try-catch. if (oos != null) try < oos.close() >catch (IOException logOrIgnore) <> and so on.
In C# you would use a using , but any exceptions thrown from the Dispose method on the IDisposable would just bubble up, so the equivalent Java would be to throw a RuntimeException on the catch of the close statement. But I don't know if the .NET system libraries swallow such exceptions by default or not.
There should be a canonical question for this -- there are a raft of very similar questions, and a searcher/reader has a hard time figuring out which to follow. Can some moderator type figure out how to merge some of these questions?
8 Answers 8
Note that the following is only applicable for Java 6 and earlier. For Java 7 and later, you should switch to using try-with-resources . as described in other answers.
If you are trying to catch and report all exceptions at source (in Java 6 or earlier), a better solution is this:
ObjectOutputStream oos = null; try < oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(shapes); oos.flush(); >catch (FileNotFoundException ex) < // complain to user >catch (IOException ex) < // notify user >finally < if (oos != null) < try < oos.close(); >catch (IOException ex) < // ignore . any significant errors should already have been // reported via an IOException from the final flush. >> >
- The standard Java wrapper streams, readers and writers all propagate close and flush to their wrapped streams, etc. So you only need to close or flush the outermost wrapper.
- The purpose of flushing explicitly at the end of the try block is so that the (real) handler for IOException gets to see any write failures 1 .
- When you do a close or flush on an output stream, there is a "once in a blue moon" chance that an exception will be thrown due to disc errors or file system full. You should not squash this exception!.
If you often have to "close a possibly null stream ignoring IOExceptions", then you could write yourself a helper method like this:
public void closeQuietly(Closeable closeable) < if (closeable != null) < try < closeable.close(); >catch (IOException ex) < // ignore >> >
then you can replace the previous finally block with:
Another answer points out that a closeQuietly method is already available in an Apache Commons library . if you don't mind adding a dependency to your project for a 10 line method.
But be careful that you only use closeQuietly on streams where IO exceptions really are irrelevant.
UPDATE : closeQuietly is deprecated in version 2.6 of the Apache Commons API. Java 7+ try-with-resources makes it redundant.
On the issue of flush() versus close() that people were asking about in comments:
- The standard "filter" and "buffered" output streams and writers have an API contract that states that close() causes all buffered output to be flushed. You should find that all other (standard) output classes that do output buffering will behave the same way. So, for a standard class it is redundant to call flush() immediately before close() .
- For custom and 3rd-party classes, you need to investigate (e.g. read the javadoc, look at the code), but any close() method that doesn't flush buffered data is arguably broken.
- Finally, there is the issue of what flush() actually does. What the javadoc says is this (for OutputStream . )
If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.