Groovy file operations - execute around pattern in action
In an older post, I described Execute Around Pattern. In this post, let's understand how this pattern simplifies the solution while reading from files and writing to files.
Suppose we have a text file that contains a few names one name per line. We want our program to read the file and print the names comma separated. Let's start with the following code.
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
Path sourcePath = Paths.get('/Users/naresha/temp/names.txt')
BufferedReader reader = Files.newBufferedReader(sourcePath);
List<String> names = reader.readLines()
println names.join(", ")
Note that I have used Java nio2 APIs. If you are used to the traditional java.io.File
based APIs, this post can help you to transition to the nio2 APIs.
java.nio.file.Files
provides newBufferedReader
static factory method. I choose to use this factory method instead of invoking the constructor. You may want to recall the first recommendation from the famous book 'Effective Java' - consider static factory methods instead of constructors.
Also Groovy provides a convenient readLines()
extension method on the objects of Reader
.
Now the code looks quite simple, isn't it? Until we realise that we forgot to close the reader. While what you want to do with the text file(read the entire content or read part of it) varies from context to context, you always create a reader object before reading the content and close the reader post read operation. Now, do you see the pattern here? We can easily reuse the pre and post reading code by using the Execute Around pattern.
import java.nio.file.Path
import java.nio.file.Paths
Path sourcePath = Paths.get('/Users/naresha/temp/names.txt')
String commaSeperatedNames = sourcePath.withReader { reader ->
List<String> names = reader.readLines()
names.join(", ")
}
println commaSeperatedNames
In the above code, withReader
method creates an instance of BufferedReader
from the path on which the method is invoked. Then it invokes the closure by passing the reader object as the argument. Finally, it closes the reader object before returning the value obtained by invoking the closure.
Similarly, Groovy provides withWriter
method for writing to a text file, which creates a writer object and closes it after performing the operations as specified by the closure that you pass as the argument.