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