Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to use try-catch (IOException) for BufferedWriter.write nested in if-else?

I have a block to write data(string) using BufferedWriter, but compiler keeps saying error: unreported exception IOException; must be caught or declared to be thrown this.dataContainer.stream().forEach( line -> writer.write(line) );

The BufferWrite.write() is already inside a try-catch block.
Is the error caused by it nested inside if-else?
How shall it be written?

void saveData() throws IOException {
        
String filename;
Path filePath; 
BufferedWriter writer;
    
filename = "missionImpossible9.csv";
filePath = this.dirPath.resolve(filename); //make path of this file
writer = Files.newBufferedWriter(filePath); 
        
try {
    if (condition1) {
       this.dataContainer1.stream().forEach( line -> writer.write(line) );
     } else {
       this.dataContainer2.stream().forEach( line -> writer.write(line) );
     }
     writer.close();
} catch (IOException err){
    err.getStackTrace();}
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem is that the method write() of BufferedWriter is declared as throwing IOException, but you’re calling it inside a Consumer<?> (the .forEach()) which is not supposed to throw any checked exception:

this.dataContainer1.stream().forEach( line -> writer.write(line) );

The expression line -> writer.write(line) is a lambda expression implementing the functional interface Consumer, and you can’t throw checked exceptions (such as IOException) inside a lambda.

The way to solve the issue is to catch the IOException inside the lambda itself, and rethrow it wrapped into a RuntimeException (which is unchecked):

this.dataContainer1.stream().forEach(line -> {
        try {
            writer.write(line); //try code that throws a checked exception
        } catch (IOException e) { //catch that checked exception
            throw new RuntimeException(e); //rethrow it as the cause of a runtime (unchecked) exception
        }
    });

At this point you don’t need to catch IOException any longer (in any case, if an IOException occurs from write() you will receive it as a RuntimeException having cause that IOException.

Note: there are nicer ways to keep the type IOException without the compiler complaining, which is called Sneaky Throw. You may want to read this article about it: Sneaky throws article.
Generally speaking it’s not suggested to silent a checked exception like this, but sometimes there’s no other choice (for example when you want to run code inside a lambda expression and you need to use a functional interface that doesn’t throw, such as Consumer).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading