注册

深度探索 Gradle 自动化构建技术(二、Groovy 筑基篇)(3)

四、文件处理


1、常规文件处理


1)、读文件


eachLine 方法


我们可以使用 eachLine 方法读该文件中的每一行,它唯一的参数是一个 Closure,Closure 的参数是文件每一行的内容。示例代码如下所示:


def file = new File(文件名)
file.eachLine{ String oneLine ->
println oneLine
}

def text = file.getText()
def text2 = file.readLines()

file.eachLine { oneLine, lineNo ->
println "${lineNo} ${oneLine}"
}
复制代码

然后,我们可以使用 'targetFile.bytes' 直接得到文件的内容。


使用 InputStream


此外,我们也可以通过流的方式进行文件操作,如下代码所示:


//操作 ism,最后记得关掉
def ism = targetFile.newInputStream()
// do sth
ism.close
复制代码

使用闭包操作 inputStream


利用闭包来操作 inputStream,其功能更加强大,推荐使用这种写法,如下所示:


targetFile.withInputStream{ ism ->
// 操作 ism,不用 close。Groovy 会自动替你 close
}
复制代码

2)、写文件


关于写文件有两种常用的操作形式,即通过 withOutputStream/withInputStream 或 withReader/withWriter 的写法。示例代码如下所示:


通过 withOutputStream/、withInputStream copy 文件


def srcFile = new File(源文件名)
def targetFile = new File(目标文件名) targetFile.withOutputStream{ os->
srcFile.withInputStream{ ins->
os << ins //利用 OutputStream 的<<操作符重载,完成从 inputstream 到 OutputStream //的输出
}
}
复制代码

通过 withReader、withWriter copy 文件


def copy(String sourcePath, String destationPath) {
try {
//首先创建目标文件
def desFile = new File(destationPath)
if (!desFile.exists()) {
desFile.createNewFile()
}

//开始copy
new File(sourcePath).withReader { reader ->
def lines = reader.readLines()
desFile.withWriter { writer ->
lines.each { line ->
writer.append(line + "\r\n")
}
}
}
return true
} catch (Exception e) {
e.printStackTrace()
}
return false
}
复制代码

此外,我们也可以通过 withObjectOutputStream/withObjectInputStream 来保存与读取 Object 对象。示例代码如下所示:


保存对应的 Object 对象到文件中


def saveObject(Object object, String path) {
try {
//首先创建目标文件
def desFile = new File(path)
if (!desFile.exists()) {
desFile.createNewFile()
}
desFile.withObjectOutputStream { out ->
out.writeObject(object)
}
return true
} catch (Exception e) {
}
return false
}
复制代码

从文件中读取 Object 对象


def readObject(String path) {
def obj = null
try {
def file = new File(path)
if (file == null || !file.exists()) return null
//从文件中读取对象
file.withObjectInputStream { input ->
obj = input.readObject()
}
} catch (Exception e) {

}
return obj
}
复制代码

2、XML 文件操作


1)、获取 XML 数据


首先,我们定义一个包含 XML 数据的字符串,如下所示:


final String xml = '''
<response version-api="2.0">
<value>
<books id="1" classification="android">
<book available="20" id="1">
<title>疯狂Android讲义</title>
<author id="1">李刚</author>
</book>
<book available="14" id="2">
<title>第一行代码</title>
<author id="2">郭林</author>
</book>
<book available="13" id="3">
<title>Android开发艺术探索</title>
<author id="3">任玉刚</author>
</book>
<book available="5" id="4">
<title>Android源码设计模式</title>
<author id="4">何红辉</author>
</book>
</books>
<books id="2" classification="web">
<book available="10" id="1">
<title>Vue从入门到精通</title>
<author id="4">李刚</author>
</book>
</books>
</value>
</response>
'''
复制代码

然后,我们可以 使用 XmlSlurper 来解析此 xml 数据,代码如下所示:


def xmlSluper = new XmlSlurper()
def response = xmlSluper.parseText(xml)

// 通过指定标签获取特定的属性值
println response.value.books[0].book[0].title.text()
println response.value.books[0].book[0].author.text()
println response.value.books[1].book[0].@available

def list = []
response.value.books.each { books ->
//下面开始对书结点进行遍历
books.book.each { book ->
def author = book.author.text()
if (author.equals('李刚')) {
list.add(book.title.text())
}
}
}
println list.toListString()
复制代码

2)、获取 XML 数据的两种遍历方式


获取 XML 数据有两种遍历方式:深度遍历 XML 数据 与 广度遍历 XML 数据,下面我们看看它们各自的用法,如下所示:


深度遍历 XML 数据


def titles = response.depthFirst().findAll { book ->
return book.author.text() == '李刚' ? true : false
}
println titles.toListString()
复制代码

广度遍历 XML 数据


def name = response.value.books.children().findAll { node ->
node.name() == 'book' && node.@id == '2'
}.collect { node ->
return node.title.text()
}
复制代码

在实际使用中,我们可以 利用 XmlSlurper 求获取 AndroidManifest.xml 的版本号(versionName),代码如下所示:


def androidManifest = new XmlSlurper().parse("AndroidManifest.xml") println androidManifest['@android:versionName']
或者
println androidManifest.@'android:versionName'
复制代码

3)、生成 XML 数据


除了使用 XmlSlurper 解析 XML 数据之外,我们也可以 使用 xmlBuilder 来创建 XML 文件,如下代码所示:


/**
* 生成 xml 格式数据
* <langs type='current' count='3' mainstream='true'>
<language flavor='static' version='1.5'>Java</language>
<language flavor='dynamic' version='1.6.0'>Groovy</language>
<language flavor='dynamic' version='1.9'>JavaScript</language>
</langs>
*/
def sw = new StringWriter()
// 用来生成 xml 数据的核心类
def xmlBuilder = new MarkupBuilder(sw)
// 根结点 langs 创建成功
xmlBuilder.langs(type: 'current', count: '3',
mainstream: 'true') {
//第一个 language 结点
language(flavor: 'static', version: '1.5') {
age('16')
}
language(flavor: 'dynamic', version: '1.6') {
age('10')
}
language(flavor: 'dynamic', version: '1.9', 'JavaScript')
}

// println sw

def langs = new Langs()
xmlBuilder.langs(type: langs.type, count: langs.count,
mainstream: langs.mainstream) {
//遍历所有的子结点
langs.languages.each { lang ->
language(flavor: lang.flavor,
version: lang.version, lang.value)
}
}

println sw

// 对应 xml 中的 langs 结点
class Langs {
String type = 'current'
int count = 3
boolean mainstream = true
def languages = [
new Language(flavor: 'static',
version: '1.5', value: 'Java'),
new Language(flavor: 'dynamic',
version: '1.3', value: 'Groovy'),
new Language(flavor: 'dynamic',
version: '1.6', value: 'JavaScript')
]
}
//对应xml中的languang结点
class Language {
String flavor
String version
String value
}
复制代码

4)、Groovy 中的 json


我们可以 使用 Groovy 中提供的 JsonSlurper 类去替代 Gson 解析网络响应,这样我们在写插件的时候可以避免引入 Gson 库,其示例代码如下所示:


def reponse =
getNetworkData(
'http://yuexibo.top/yxbApp/course_detail.json')

println reponse.data.head.name

def getNetworkData(String url) {
//发送http请求
def connection = new URL(url).openConnection()
connection.setRequestMethod('GET')
connection.connect()
def response = connection.content.text
//将 json 转化为实体对象
def jsonSluper = new JsonSlurper()
return jsonSluper.parseText(response)
}
复制代码

五、总结


在这篇文章中,我们从以下 四个方面 学习了 Groovy 中的必备核心语法:



  • 1)、groovy 中的变量、字符串、循环等基本语法。
  • 2)、groovy 中的数据结构:数组、列表、映射、范围。
  • 3)、groovy 中的方法、类等面向对象、强大的运行时机制。
  • 4)、groovy 中对普通文件、XML、json 文件的处理。

在后面我们自定义 Gradle 插件的时候需要使用到这些技巧,因此,掌握好 Groovy 的重要性不言而喻,只有扎实基础才能让我们走的更远。


作者:jsonchao
链接:https://juejin.cn/post/6844904128594853902
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1 个评论

写得好

要回复文章请先登录注册