Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

In this quick tutorial, we'll explore different ways of reading a file in Groovy.

Groovy provides convenient ways to handle files. We'll concentrate on the File class which has some helper methods for reading files.

Let's explore them one by one in the following sections.

2. Reading a File Line by Line

There are many Groovy IO methods like readLine and eachLine available for reading files line by line.

2.1. Using File.withReader

Let's start with the File.withReader method. It creates a new BufferedReader under the covers that we can use to read the contents using the readLine method.

For example, let's read a file line by line and print each line. We'll also return the number of lines:

int readFileLineByLine(String filePath) {
    File file = new File(filePath)
    def line, noOfLines = 0;
    file.withReader { reader ->
        while ((line = reader.readLine()) != null) {
            println "${line}"
            noOfLines++
        }
    }
    return noOfLines
}

Let's create a plain text file fileContent.txt with the following contents and use it for the testing:

Line 1 : Hello World!!!
Line 2 : This is a file content.
Line 3 : String content

Let's test out our utility method:

def 'Should return number of lines in File given filePath' () {
    given:
        def filePath = "src/main/resources/fileContent.txt"
    when:
        def noOfLines = readFile.readFileLineByLine(filePath)
    then:
        noOfLines
        noOfLines instanceof Integer
        assert noOfLines, 3
}

The withReader method can also be used with a charset parameter like UTF-8 or ASCII to read encoded files. Let's see an example:

new File("src/main/resources/utf8Content.html").withReader('UTF-8') { reader ->
def line
    while ((line = reader.readLine()) != null) { 
        println "${line}"
    }
}

2.2. Using File.eachLine

We can also use the eachLine method:

new File("src/main/resources/fileContent.txt").eachLine { line ->
    println line
}

2.3. Using File.newInputStream with InputStream.eachLine

Let’s see how we can use the InputStream with eachLine to read a file:

def is = new File("src/main/resources/fileContent.txt").newInputStream()
is.eachLine { 
    println it
}
is.close()

When we use the newInputStream method, we have to deal with closing the InputStream.

If we use the withInputStream method instead, it will handle closing the InputStream for us:

new File("src/main/resources/fileContent.txt").withInputStream { stream ->
    stream.eachLine { line ->
        println line
    }
}

3. Reading a File into a List

Sometimes we need to read the content of a file into a list of lines.

3.1. Using File.readLines

For this, we can use the readLines method which reads the file into a List of Strings.

Let's have a quick look at an example that reads file content and returns a list of lines:

List<String> readFileInList(String filePath) {
    File file = new File(filePath)
    def lines = file.readLines()
    return lines
}

Let's write a quick test using fileContent.txt:

def 'Should return File Content in list of lines given filePath' () {
    given:
        def filePath = "src/main/resources/fileContent.txt"
    when:
        def lines = readFile.readFileInList(filePath)
    then:
        lines
        lines instanceof List<String>
        assert lines.size(), 3
}

3.2. Using File.collect

We can also read the file content into a List of Strings using the collect API:

def list = new File("src/main/resources/fileContent.txt").collect {it}

3.3. Using the as Operator

We can even leverage the as operator to read the contents of the file into a String array:

def array = new File("src/main/resources/fileContent.txt") as String[]

4. Reading a File into a Single String

4.1. Using File.text

We can read an entire file into a single String simply by using the text property of the File class.

Let's have a look at an example:

String readFileString(String filePath) {
    File file = new File(filePath)
    String fileContent = file.text
    return fileContent
}

Let's verify this with a unit test:

def 'Should return file content in string given filePath' () {
    given:
        def filePath = "src/main/resources/fileContent.txt"
    when:
        def fileContent = readFile.readFileString(filePath)
    then:
        fileContent
        fileContent instanceof String
        fileContent.contains("""Line 1 : Hello World!!!
Line 2 : This is a file content.
Line 3 : String content""")
}

4.2. Using File.getText

If we use the getTest(charset) method, we can read the content of an encoded file into a String by providing a charset parameter like UTF-8 or ASCII:

String readFileStringWithCharset(String filePath) {
    File file = new File(filePath)
    String utf8Content = file.getText("UTF-8")
    return utf8Content
}

Let's create an HTML file with UTF-8 content named utf8Content.html for the unit testing:

ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ
ᛋᚳᛖᚪᛚ᛫ᚦᛖᚪᚻ᛫ᛗᚪᚾᚾᚪ᛫ᚷᛖᚻᚹᛦᛚᚳ᛫ᛗᛁᚳᛚᚢᚾ᛫ᚻᛦᛏ᛫ᛞᚫᛚᚪᚾ
ᚷᛁᚠ᛫ᚻᛖ᛫ᚹᛁᛚᛖ᛫ᚠᚩᚱ᛫ᛞᚱᛁᚻᛏᚾᛖ᛫ᛞᚩᛗᛖᛋ᛫ᚻᛚᛇᛏᚪᚾ

Let's see the unit test:

def 'Should return UTF-8 encoded file content in string given filePath' () {
    given:
        def filePath = "src/main/resources/utf8Content.html"
    when:
        def encodedContent = readFile.readFileStringWithCharset(filePath)
    then:
        encodedContent
        encodedContent instanceof String
}

5. Reading a Binary File with File.bytes

Groovy makes it easy to read non-text or binary files. By using the bytes property, we can get the contents of the File as a byte array:

byte[] readBinaryFile(String filePath) {
    File file = new File(filePath)
    byte[] binaryContent = file.bytes
    return binaryContent
}

We'll use a png image file, sample.png, with the following contents for the unit testing:

 

Let's see the unit test:

def 'Should return binary file content in byte array given filePath' () {
    given:
        def filePath = "src/main/resources/sample.png"
    when:
        def binaryContent = readFile.readBinaryFile(filePath)
    then:
        binaryContent
        binaryContent instanceof byte[]
        binaryContent.length == 329
}

6. Conclusion

In this quick tutorial, we've seen different ways of reading a file in Groovy using various methods of the File class along with the BufferedReader and InputStream.

The complete source code of these implementations and unit test cases can be found in the GitHub project.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!