1. 概述

在本篇快速教程中,我们将深入探讨如何在 Groovy 中读取文件。

Groovy 提供了多种便捷的方式来处理文件操作。本文将重点介绍 File 类中用于读取文件内容的一些实用方法。

接下来我们将逐一分析这些方法的使用方式和适用场景。

2. 逐行读取文件

Groovy 提供了多个用于逐行读取文件内容的方法,如 readLineeachLine 等。

2.1 使用 File.withReader

File.withReader 方法会自动创建一个 BufferedReader 实例,我们可以使用该实例来逐行读取文件内容。

示例:逐行读取并打印文件内容,并返回总行数:

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
}

准备一个测试文件 fileContent.txt 内容如下:

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

编写单元测试验证功能是否正常:

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

提示withReader 方法也支持传入字符集参数(如 UTF-8 或 ASCII),方便读取编码后的文件内容。

示例:

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

2.2 使用 File.eachLine

另一种更简洁的方式是使用 eachLine 方法:

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

这个方法会自动处理资源关闭问题,使用起来非常方便。

2.3 使用 File.newInputStream 配合 InputStream.eachLine

我们也可以通过 newInputStream 获取输入流,然后调用 eachLine 方法读取文件:

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

⚠️ 注意:使用 newInputStream 时需要手动关闭输入流。

为了避免手动管理资源,可以使用 withInputStream 方法:

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

3. 将文件读入 List

有时我们需要将整个文件内容读入一个字符串列表中。

3.1 使用 File.readLines

readLines 方法可以直接将文件内容读取为 List<String>

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

单元测试示例:

def 'Should return File Content in list of lines using ReadFile.readFileInList 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 使用 File.collect

也可以使用 collect 方法将文件内容收集到一个列表中:

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

3.3 使用 as 操作符

还可以使用 as 操作符将文件内容转换为字符串数组:

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

4. 将文件读入单个 String

4.1 使用 File.text

最简单粗暴的方式就是直接访问 File 对象的 text 属性,即可将整个文件读入一个字符串:

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

单元测试验证:

def 'Should return file content in string using ReadFile.readFileString 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"].join("\r\n"))
}

4.2 使用 File.getText

如果需要指定字符集(如 UTF-8),可使用 getText(charset) 方法:

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

准备一个包含 UTF-8 编码内容的 HTML 文件 utf8Content.html

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

单元测试验证:

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

5. 读取二进制文件:File.bytes

对于非文本文件(如图片、音频等),Groovy 提供了 bytes 属性来获取文件的字节内容:

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

我们使用一张 PNG 图片 sample.png 进行测试:

sample

单元测试如下:

def 'Should return binary file content in byte array using ReadFile.readBinaryFile 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. 总结

本文介绍了 Groovy 中常用的几种文件读取方式,涵盖了逐行读取、读入列表、读入字符串以及读取二进制文件等常见需求。

每种方法都有其适用场景,选择合适的 API 可以显著提升开发效率。

完整的代码示例及单元测试可以在 GitHub 项目中找到:GitHub


原始标题:Reading a File in Groovy