This article was originally posted on JRoller on March 12, 2015
You should always close your IO streams. Said like this, it sounds obvious. But in the light of some new Java 8 features, it took me some time to get around it.
I needed to write a small method for modifying a CSV file, basically change the last 1 of each line into a 0. Not really difficult. I would create a temporary file where I'll copy the original lines with the needed modification, then overwrite the original file with the one I created. Since I could use Java 8, I thought I would use a stream and lambdas. The code looked like this:
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(tempFile))) { Files.lines(toConvert) .map(line -> line.replace(";1", ";0")) .forEach(line -> writer.println(line)); } Files.move(tempFile, toConvert, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
Looks nice, except I had this weird java.nio.file.FileSystemException with the message "The process cannot access the file because it is being used by another process.". I was pretty sure that the only process using my file was my small program. So the problem was that the Files.lines() does not close the file. I found other references on the net to comfort my idea. So yes, I know, you can find it in the javadocs, and yes, the stream is autocloseable. So the way to go is the following:
try (Stream<String> reader = Files.lines(toConvert)) {
reader.map(line -> line.replace(";1", ";0"))
.forEach(line -> writer.println(line));
}
But to my defense, I'm not the only one having problems with the javadocs: https://bugs.openjdk.java.net/browse/JDK-8073923