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