-2

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();
    }
}

Still, I get this error:

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
  1. Where did I "already catch" FileNotFoundException?
  2. 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?

EDIT:

If I do:

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();

    }
}

I get:

FileIO.java:20: error: unreported exception IOException; must be caught or declared to be thrown
                out.close();
                         ^
1 error
Ravi
  • 30,829
  • 42
  • 119
  • 173
Sahand
  • 7,980
  • 23
  • 69
  • 137
  • Your other question is probably answered here: [Java catching exceptions and subclases](https://stackoverflow.com/q/6707320). 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. – Bernhard Barker Feb 04 '18 at 17:08
  • @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). – Bernhard Barker Feb 04 '18 at 17:10
  • @Dukeling are you suggesting me to rollback ? – Ravi Feb 04 '18 at 17:16
  • @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. – Bernhard Barker Feb 04 '18 at 17:24
  • @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. :-) – Ravi Feb 04 '18 at 17:32

5 Answers5

3

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){

}
Ravi
  • 30,829
  • 42
  • 119
  • 173
  • Thanks. What about question two? – Sahand Feb 04 '18 at 16:01
  • @Sahand answered already. Let me know, if you have any specific question. – Ravi Feb 04 '18 at 16:04
  • It's not, the same error persists with your solution. – Sahand Feb 04 '18 at 16:08
  • 1
    @Sahand I have noticed many times, you seems to have habit of downvoting immediately. You should have patience and ask back and forth question. – Ravi Feb 04 '18 at 16:10
  • Okay. What is the point of catching them like that in sequence if FileNotFoundException already catches IOException on its own? I only need FileNotFoundException, right? – Sahand Feb 04 '18 at 16:15
  • @Sahand IOException is base class of many other exception and `FileNotFoundException` specific to file not found exception. What if you get exception while writing ?? It is your choice, it isn't forced by anyone to catch `FileNotFoundException` as well. – Ravi Feb 04 '18 at 16:16
  • Well the exception while writing will not be caught by your double clause anyway since it will occur in the finally block and you already recommended to make a separate try and catch there. – Sahand Feb 04 '18 at 16:18
  • @Sahand No, you misunderstood completely. In finally block you are closing the resource, which throw IOException. And, that is the reason, I suggested to use try-with-resource. It will take care of closing resource at the end. – Ravi Feb 04 '18 at 16:19
  • Then I don't think your solution works, unless I've misunderstood you again. I've added an explanation in an edit. – Sahand Feb 04 '18 at 16:22
  • @Sahand you are not at all getting my point. I will update my post. – Ravi Feb 04 '18 at 16:25
  • @Sahand I have updated the post with example. – Ravi Feb 04 '18 at 16:30
  • Thanks. Do I have to catch exceptions even with try-with-resource? – Sahand Feb 04 '18 at 16:36
  • 1
    @Sahand Yes. It only take cares of closing resource else it is same as older version – Ravi Feb 04 '18 at 16:39
1

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){

    }
    }
        }
    }
Sahand
  • 7,980
  • 23
  • 69
  • 137
Jayanth
  • 746
  • 6
  • 17
0

Since FileNotFoundException extends IOException, then just by catching IOException you are catching all subtypes of IOException.

And regarding your second question, since `.close()` method also throws `IOException`, you can put all the IO code in a method, and have that method to throw `IOException`, then the caller can deal with the any exceptions.

for example:

private static void writeToFile() throws IOException{
 FileInputStream in = null;
    FileOutputStream out = null;
    String content = "hello";
    byte[] contentBytes = content.getBytes();
    try{
        out = new FileOutputStream("output.txt");
        out.write(contentBytes);
    }finally{
        if (out != null)
            out.close();
    }
}

and then your main would look like this.

public static void main(String[] args){
    FileInputStream in = null;
    FileOutputStream out = null;
    String content = "hello";
    byte[] contentBytes = content.getBytes();

    try{
       writeToFile();
    }catch(IOException e){

    }
}

And have a look at tryResourceClose

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
QuakeCore
  • 1,886
  • 2
  • 15
  • 33
0
public static void main(String[] args) throws IOException{
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();

try{
    out = new FileOutputStream("output.txt");
    out.write(contentBytes);
}catch(FileNotFoundException e){

}
finally{
        if (out != null)
        out.close();

}

}

kamoloff
  • 118
  • 1
  • 9
0
String outputPath = "output.txt";
String content = "hello";
byte[] contentBytes = content.getBytes();
try (FileOutputStream out = new FileOutputStream(outputPath)) {
    out.write(contentBytes);
} catch (FileNotFoundException e) {
    System.err.println("Failed to find the file to write to: " + outputPath);
} catch (IOException e) {
    System.err.println("Failed to write to file: " + outputPath);
}

As QuakeCore mentioned FileNotFoundEception extends IOException, this is why you should catch FileNotFoundEception first.

It is a good practice to print at least some message, so you will not be surprised when there is no output and no exceptions in console / logs.

FileOutputStream implements AutoClosable interface. This why it is better to use try with resources. In this case JVM will close it automatically.

uli
  • 671
  • 6
  • 15