bingoogolapple / bingoogolapple.github.io

个人主页。同时也通过 Issues 记录学习笔记
http://www.bingoogolapple.cn
86 stars 22 forks source link

Groovy #106

Open bingoogolapple opened 8 years ago

bingoogolapple commented 8 years ago

image


image


image

bingoogolapple commented 6 years ago

变量定义

// 弱类型定义方式:用 def 定义变量时可以动态类型转换
def a = 1
println a.class // class java.lang.Integer

a = 3.14
println a.class // class java.math.BigDecimal

a = "BGA"
println a.class // class java.lang.String

// 也可以不用 def,直接给变量赋值
b = 3.14
println b.class // class java.math.BigDecimal

b = "BGA"
println b.class // class java.lang.String

// 强类型定义方式:用具体类型定义变量时,同父类型可以转换,和 Java 一样
int c = 1
println c.class // class java.lang.Integer

c = 3.14
println c // 3
println c.class // class java.lang.Integer 不会被转换成 java.math.BigDecimal

c = "BGA"
println c.class
/*
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'BGA' with class 'java.lang.String' to class 'int'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'BGA' with class 'java.lang.String' to class 'int'
        at study.variable.run(variable.groovy:18)
 */
bingoogolapple commented 6 years ago

数字

int a = 10
println a.class // class java.lang.Integer
println 10.class // class java.lang.Integer
float b = 3.14
println b.class // class java.lang.Float
double c = 3.14
println c.class // class java.lang.Double
println 3.14f.class // class java.lang.Float
println 3.14.class // class java.math.BigDecimal
println 3.class // class java.lang.Integer
short d = 1
println d.class // class java.lang.Short
byte e = 1
println e.class // class java.lang.Byte

def f = 11
println f.class // class java.lang.Integer
def g = 3.14f
println g.class // class java.lang.Float
def h = 3.14
println h.class // class java.math.BigDecimal

// 这里的加号是 NumberNumberPlus 的 plus 方法
println 5.889f + 5.889f  // 11.777999877929688 // 最终会转换成 Double 的 add 方法
println 5.889 + 5.889 // 11.778 最终会转换成 BigDecimal 的 add 方法
println 5.889.add(5.889) // 11.778
bingoogolapple commented 6 years ago

字符串

def b = "B'G'A" println b.class // class java.lang.String

def c = 'B"G"A' println c.class // class java.lang.String

// 原样输出,开始的'''后面和结束的'''前面巧回车时输出会自动换行,不想自动换行的话加上反斜线 def d = ''' BGA BGA BGA\ ''' println d.class // class java.lang.String println d

def e = "bingoogolapple$c${(2 + 3) * 5}${"hello".capitalize()}" // 支持任意表达式 println e // bingoogolappleBGA25Hello println e.class // class org.codehaus.groovy.runtime.GStringImpl Groovy 中特有的 GString

def f = echo1(e) println f.class // class java.lang.String def g = echo2(e) println g.class // class org.codehaus.groovy.runtime.GStringImpl def h = echo2(b) println h.class // class java.lang.String

// static String echo1(def message) { // 不管传入的是 String 还是 GString,返回的始终是 String // static def echo1(String message) { // 不管传入的是 String 还是 GString,返回的始终是 String static String echo1(String message) { // 不管传入的是 String 还是 GString,返回的始终是 String return message }

static def echo2(def message) { // 传入什么类型返回的就是什么类型 return message }

// 三个单引号时不支持表达式拼接 def i = ''' BGA BGA${(11 + 22) / 3} BGA\ ''' println i.class println i // 三个双引号时支持任意表达式拼接 def j = """ BGA BGA${(11 + 22) / 3} BGA\ """ println j.class // class org.codehaus.groovy.runtime.GStringImpl println j

* 常用方法
```groovy
/*
三个来源:
java.lang.String
DefaultGroovyMethods
StringGroovyMethods
 */

// 填充到指定长度,第二个参数为要填充的值,默认填充空格
println '1111'.center(8, '2') // 22111122
println '11111'.center(8, '2') // 21111122
println '1111'.padLeft(8, '2') // 22221111
println '1111'.padRight(8, '2') // 11112222

println '1111'.leftShift('2') // 11112 leftShift 可以用 << 操作符替换
println '1111' << '2' // 11112 // 内部实现 new StringBuffer('1111').append('2')

// 从左边第一个字符开始比较,如果前面的字符都相等则比较长度
println '111'.compareTo('22') // -1 等价于操作符 <=>
println '111' <=> '22' // -1
println '111' > '22' // false
println '3' > '22' // true
println '22' <=> '22' // true

println 'BGA'.charAt(0) // B 等价 [0] 来获取
println 'BGA'[0] // B
println 'BGA'[0, 1] // BG 逗号分隔,获取指定1个或多个位置的值
println 'BGA'[0, 2] // BA 逗号分隔,获取指定1个或多个位置的值
println 'BGA'[1..2] // BGA .. 分隔,获取指定返回的值

println 'bingoogolapple' - 'apple' - 'bingo' // ogol

println 'hello world'.capitalize() // Hello world 句子首字母大写
println 'hello world'.split(' ').collect { it.capitalize() }.join(' ') // Hello World 每个单词首字母大写
println 'HELLO WORLD'.uncapitalize() // hELLO WORLD 句子首字母小写
println 'HELLO WORLD'.split(' ').collect { it.uncapitalize() }.join(' ') // hELLO wORLD 每个单词首字母小写

println 'BGA'.reverse() // AGB

println 'BGA'.asBoolean() // true 对比长度是否大于 0
println 'BGA'.toBoolean() // false 对比是否为字符串 true、y、0
bingoogolapple commented 6 years ago

闭包

def helloClosure1 = { param ->
    println "Hello Closure $param"
}
println helloClosure1.class // class cn.bingoogolapple.dsl.groovy.7_closure$_run_closure1
helloClosure1.call('bingo')
helloClosure1('googol')
helloClosure1 'apple'

def helloClosure2 = {
    println "Hello Closure $it" // 默认参数名叫 it
}
helloClosure2 'bingo'

def helloClosure3 = { name, age ->
    println "Hello Closure $name $age"
}
def helloClosure4 = { String name, int age ->
    println "Hello Closure $name $age"
}

helloClosure3('BGA', 26)
helloClosure4('BGA', 26)
helloClosure4.call(["wanghao", 26]) // 也可以通过 List 来返回多个参数
helloClosure4(["wanghao", 26])

// 闭包一定是有返回值的
def helloClosure5 = {
    println "Hello Closure5"
}
def helloClosure6 = {
    return "Hello Closure6"
}
def helloClosure7 = {
    "Hello Closure7" // 如果没有写 return,则用最后一行的结果作为闭包的返回值
}
println helloClosure5() // null
println helloClosure6() // Hello Closure6
println helloClosure7() // Hello Closure7

static int factorial1(int number) {
    int result = 1
    1.upto(number, { num -> result *= num })
    return result
}

println '------------------------------------'

println factorial1(3)

static int factorial2(int number) {
    int result = 1
    number.downto(1) { num -> result *= num } // 可以将最后一个闭包参数放到小括号外面
    return result
}

println factorial2(3)

static int sum(int number) {
    int result = 0
    // 0 到 number - 1
    number.times { num ->
        result += num

//        if (num == 1) {
//            setDirective(Closure.DONE)
//        }
    }
    return result
}

println sum(3)

println '------------------------------------'

def test = 'String Closure'
test.each {
    print it.multiply(2)
}
test = '''\
line1
line2
line3\
'''
test.eachLine { line, counter -> // closure.call(new Object[]{line, counter}) 内部是通过对象数组返回参数的
    println "$line | $counter"
}
println test.find { it.isNumber() } // 1
println test.findAll { it.isNumber() }.toListString() // [1, 2, 3]
println test.any { it.isNumber() } // true 字符串中只要有一个数字就是 true
println test.every { it.isNumber() } // false 字符串中所有的都是数字才为 true
println test.collect { it.toUpperCase() }

static def testClosureParams(Closure closure) {
    println "parameterTypes ${closure.parameterTypes}"
    println "maximumNumberOfParameters ${closure.maximumNumberOfParameters}"

    if (closure.getMaximumNumberOfParameters() == 3) {
        closure('bingoogolapple', 26, 'xxxxxx')
    } else if (closure.getMaximumNumberOfParameters() == 2) {
        closure.call('bingoogolapple', 26)
        closure.call(['bingoogolapple', 26])
        closure('bingoogolapple', 26)
        closure(['bingoogolapple', 26])
    } else {
        closure.call('bingoogolapple')
    }
}

testClosureParams { String name, int age, xxx ->
    println "name $name, age $age, xxx $xxx"
}

testClosureParams { name, Integer age ->
    println "name $name, age $age"
}

testClosureParams({ name ->
    println "name $name"
})
/**
 * this:代表闭包定义处的类或对象。静态闭包时为定义处的类,非静态时为定义处的类的实例对象
 * owner:代表闭包定义处的类或对象。闭包嵌套闭包时,内层闭包的 owner 和 this 就会不一样,为外层闭包类的实例对象
 * delegate:代表任意对象,默认与 owner 一致。人为修改 delegate 时,delegate 和 owner 时就会不一样
 *
 * owner 和 thisObject 都是构成方法传入的,不能修改
 */

class Tester {
    static def classClosure = {
        println "classClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
        println "classClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester
        println "classClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester
        println '----------------------------'
        def innerClassClosure = {
            println "innerClassClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
            println "innerClassClosure outerClosureClass: " + classClosure.class // cn.bingoogolapple.dsl.groovy.Tester$__clinit__closure4
            println "innerClassClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$__clinit__closure4@1dde4cb2
            println "innerClassClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$__clinit__closure4@1dde4cb2
            println '--------------------------------------------------------'
        }
        innerClassClosure.call()
    }

    static def classMethod() {
        def classMethodClosure = {
            println "classMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
            println "classMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester
            println "classMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester
            println '----------------------------'

            def innerClassMethodClosure = {
                println "innerClassMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
                println "innerClassMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$_classMethod_closure2@5119fb47
                println "innerClassMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$_classMethod_closure2@5119fb47
                println '--------------------------------------------------------'
            }
            innerClassMethodClosure.call()
        }
        classMethodClosure.call()
    }

    def objectClosure = {
        println "objectClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
        println "objectClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
        println "objectClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
        println '----------------------------'
        def innerObjectClosure = {
            println "innerObjectClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
            println "innerObjectClosure outerClosureClass: " + objectClosure.class // cn.bingoogolapple.dsl.groovy.Tester$_closure1
            println "innerObjectClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$_closure1@1ab3a8c8
            println "innerObjectClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$_closure1@1ab3a8c8
            println '--------------------------------------------------------'
        }
        innerObjectClosure.call()
    }

    def objectMethod() {
        def objectMethodClosure = {
            println "objectMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
            println "objectMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
            println "objectMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
            println '----------------------------'
            def innerObjectMethodClosure = {
                println "innerObjectMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
                println "innerObjectMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$_objectMethod_closure3@479d31f3
                println "innerObjectMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$_objectMethod_closure3@479d31f3
                println '--------------------------------------------------------'
            }
            innerObjectMethodClosure.call()
        }
        objectMethodClosure.call()
    }
}

Tester.classClosure.call()
Tester.classMethod()
def tester = new Tester()
tester.objectClosure.call()
tester.objectMethod()

def scriptOuterClosure = {
    println "scriptOuterClosure this:" + this // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
    println "scriptOuterClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
    println "scriptOuterClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
    println '----------------------------'
    def scriptInnerClosure = {
        println "scriptInnerClosure this:" + this // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
        // println "scriptInnerClosure owner:$owner" // 在嵌套的内层 Closure 中,不能通过在字符串中直接使用 $owner 和 $delegate,否则会内存溢出
        println "scriptInnerClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.8_closureadvance$_run_closure2@c267ef4
        println "scriptInnerClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.8_closureadvance$_run_closure2@c267ef4
        println '----------------------------'
    }
    def scriptInnerTwoClosure = {
        println "scriptInnerTwoClosure this:" + this // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
        println "scriptInnerTwoClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.8_closureadvance$_run_closure2@c267ef4
        println "scriptInnerTwoClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
        println "scriptInnerTwoClosure thisObject:" + thisObject // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
        println '--------------------------------------------------------'
    }
    scriptInnerClosure.call()
    scriptInnerTwoClosure.delegate = tester // 修改默认的 delegate
    scriptInnerTwoClosure.call()
}
scriptOuterClosure.call()

class Student {
    String name
    def pretty = { "My name is ${name}" }

    String toString() {
        pretty.call()
    }
}

class Teacher {
    String name
}

def student = new Student(name: 'BGA')
def teacher = new Teacher(name: 'bingoogolapple')
println student.toString() // My name is BGA
student.pretty.delegate = teacher
println student.toString() // My name is BGA
// 修改解析策略,默认值为 Closure.OWNER_FIRST。学习委托策略时看源码中这几个常量对应注释中的 demo 更容易理解
student.pretty.resolveStrategy = Closure.DELEGATE_FIRST
println student.toString() // My name is bingoogolapple
bingoogolapple commented 6 years ago

列表

def list = [1, 2, 3, 4, 5]
println list.class // class java.util.ArrayList
println list.size()
def array = [1, 2, 3, 4, 5] as int[]
println array.class // class [I
println array.length
int[] array2 = [1, 2, 3, 4, 5]
println array2.class // class [I
println array2.length
println '------------------------'
println list.sum {
    it * 3
} // 每一项乘以 3 的和
list.add(6) // 末尾追加
println list
list.leftShift(7) // 末尾追加
println list
list << 8 // 末尾追加
println list
list.push(9) // 末尾追加
println list
println list.minus([1, 3, 5, 7, 9])
println list - [1, 3, 5, 7, 9]
println list
list.removeElement(1)
println list
list.removeAll { it % 2 == 0 }
println list
list.removeAll([7, 9])
println list
println '------------------------'
def sortList = [2, 8, 4, 6, 7, 9]
//sortList.sort() // 默认是升序
//println sortList
sortList.sort { a, b -> a == b ? 0 : a > b ? -1 : 1 }
println sortList

def sortStringList = ['kotlin', 'java', 'swift', 'python', 'shell', 'groovy']
sortStringList.sort { it -> return it.size() }
println sortStringList

def findList = [-1, 1, -2, 2, -3, 3, -4, 4]
println findList.find { return it % 2 == 0 }
println findList.findAll { return it % 2 != 0 }
println findList.any { return it % 2 != 0 } // true
println findList.every { return it % 2 == 0 } // false
println findList.min()
println findList.min { return Math.abs(it) }
println findList.max()
println findList.max { return Math.abs(it) }
println findList.count { return it % 2 == 0 }

list.each {
    println "each $it"
}
list.forEach {
    println "forEach $it"
}
list.eachWithIndex { element, index -> println "element $element, index $index" }
bingoogolapple commented 6 years ago

映射

def colors = [red: 'ff0000', green: '00ff00', blue: '0000ff']
println colors.getClass() // class java.util.LinkedHashMap
// println colors.class 不能用点操作符获取类型,map 的点操作符是获取对应 key 的值
println colors['red']
println colors.red

colors.yellow = 'ffff00'
println colors
colors.complex = [bingo: 1, googol: 2]
println colors

def students = [
        1: [number: '0001', name: 'Bob',
            score : 55, sex: 'male'],
        2: [number: '0002', name: 'Johnny',
            score : 62, sex: 'female'],
        3: [number: '0003', name: 'Claire',
            score : 73, sex: 'female'],
        4: [number: '0004', name: 'Amy',
            score : 66, sex: 'male']
]
println '\n----------------------------------------------------------'
students.each { student -> println "each entry | key $student.key, value $student.value" }
println '----------------------------------------------------------'
students.each { key, value -> println "each key value | key $key, value $value" }
println '----------------------------------------------------------'
students.eachWithIndex { student, index -> println "eachWithIndex entry | key $student.key, value $student.value, index $index" }
println '----------------------------------------------------------'
students.eachWithIndex { key, value, index -> println "eachWithIndex key value | key $key, value $value, index $index" }
println '----------------------------------------------------------\n'

def entry = students.find { studentEntry -> studentEntry.value.score >= 60 }
println entry.class
println entry
def resultMap = students.findAll { studentEntry -> studentEntry.value.score >= 60 }
println resultMap.getClass()
println resultMap

println students.count { studentEntry -> studentEntry.value.score >= 60 && studentEntry.value.sex == 'male' }

println students.findAll { studentEntry -> studentEntry.value.score >= 60 }.collect { it.value.name }.toListString()

println students.groupBy { studentEntry -> studentEntry.value.score >= 60 ? '及格' : '不及格' }

def sortedMap = students.sort { studentEntry1, studentEntry2 ->
    def score1 = studentEntry1.value.score
    def score2 = studentEntry2.value.score
    return score1 == score2 ? 0 : score1 < score2 ? -1 : 1
} // 返回一个新的 map,老的 map 没变
println sortedMap
bingoogolapple commented 6 years ago

范围

def range = 1..10
println range.class // class groovy.lang.IntRange
println range
println range[0]
println range.from
println range.to
println range.contains(10) // true
range = 1..<10
println range.contains(10) // false
range.each { println it }
for (value in range) {
    println value
}

static def getGrade(def number) {
    def result
    switch (number) {
        case 0..<60:
            result = '不及格'
            break
        case 60..<70:
            result = '及格'
            break
        case 70..<80:
            result = '良好'
            break
        case 80..100:
            result = '优秀'
            break
    }

//    return result
    result // 最后一行可以省略 return 关键字
}

println getGrade(59)
println getGrade(60)
println getGrade(90)
bingoogolapple commented 6 years ago

面向对象

interface Action {
    // protected void eat() // 接口中不许定义非 public 的方法
    void eat()

    void drink()

    void play()
}

trait DefaultAction {
    abstract void eat()

    void drink() { // 可以有默认的实现
        println "drink"
    }

    void play() {
        println "play"
    }
}

// groovy 中默认都是 public
class Person implements Serializable, DefaultAction {
    String name
    Integer age

    def increaseAge(Integer years) {
        this.age += years
    }

    // 1.类中有对应的方法直接调用类中对应的方法
    // 2.类中没有对应的方法,MetaClass 中有则调用 MetaClass 中的方法
    // 3.类中没有对应的方法,MetaClass 中也没有对应的方法,有重写 methodMissing 方法则调用 methodMissing 方法
    def methodMissing(String name, Object args) {
        return "the method ${name} is missing, the params is ${args}"
    }
    // 4.类中没有对应的方法,MetaClass 中也没有对应的方法,没有有重写 methodMissing 方法,有重写 invokeMethod 方法则调用 invokeMethod 方法
    def invokeMethod(String name, Object args) {
        return "the method is ${name}, the params is ${args}"
    }
    // 5.类中没有对应的方法,MetaClass 中也没有对应的方法,没有有重写 methodMissing 和 invokeMethod 方法,抛 MissingMethodException

    @Override
    void eat() {
        println "eat"
    }
}

def person = new Person()
// 没有对应构造方法时,可以通过名称参数来实例化
person = new Person(name: 'BGA')
person = new Person(age: 26)
person = new Person(name: 'BGA', age: 26)
// 无论是直接用点操作符还是调用 get/set 方法,最终都是调用 get/set 方法
println "the name is $person.name, the age is $person.age"
person.increaseAge(2)
println "the name is ${person.getName()}, the age is ${person.getAge()}"

//ExpandoMetaClass.enableGlobally()

// 为类动态添加属性
Person.metaClass.sex = 'male'
println person.sex // 动态增加属性只对修改 metaClass 后创建的对象生效,修改之前已经创建的对象不会生效
person = new Person(name: 'BGA', age: 26, sex: 'qwer')
println person.sex // qwer
person = new Person(name: 'BGA', age: 26)
println person.sex // male
person.sex = 'female'
println person.sex // female

// 为类动态添加方法
Person.metaClass.testSdf = { param1, param2 ->
    println "param1 $param1, param2 $param2"
    return name.toLowerCase()
}
println person.testSdf('aaaa', 'bbbb') // 动态增加方法对修改 metaClass 前后创建的对象都生效
person = new Person(name: 'ABC', age: 26)
println person.testSdf('aaaa', 'bbbb')

// 为类动态的添加静态方法
Person.metaClass.static.createPerson = { name, age -> new Person(name: name, age: age, sex: 'female') }
person = Person.createPerson('AAAABBBB', 26)
println "name $person.name, age $person.age, sex $person.sex"
bingoogolapple commented 6 years ago

JSON 解析

import groovy.json.JsonOutput
import groovy.json.JsonSlurper

def list = [new Person(name: 'BGA', age: 26),
            new Person(name: 'bingoogolapple', age: 26)]
def jsonStr = JsonOutput.toJson(list)
println JsonOutput.prettyPrint(jsonStr)

def jsonSlurper = new JsonSlurper()
println jsonSlurper.parseText(jsonStr)

def responseText = 'http://www.wanandroid.com/banner/json'.toURL().text
def responseJson = new JsonSlurper().parseText(responseText)
println responseJson.data[0].desc
bingoogolapple commented 6 years ago

XML 解析

import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder

def writeXml() {
    def responseText = 'http://www.wanandroid.com/banner/json'.toURL().text
    def responseJson = new JsonSlurper().parseText(responseText)

    def stringWriter = new StringWriter()
    // 用来生成 xml 数据的核心类
    def xmlBuilder = new MarkupBuilder(stringWriter)
    //根结点 ResponseData 创建成功
    xmlBuilder.ResponseData() {
        errorCode(responseJson.errorCode)
        errorMsg(responseJson.errorMsg)
        data() {
            responseJson.data.each {
                banner(desc: it.desc, id: it.id, title: it.title, it.imagePath)
            }
        }
    }
    println stringWriter
}

writeXml()
println '------------------------------------------------------------------------'

def xmlStr = '''\
<ResponseData>
  <errorCode>0</errorCode>
  <errorMsg></errorMsg>
  <data>
    <banner desc='最新项目上线啦~' id='13' title='最新项目上线啦~'>http://www.wanandroid.com/blogimgs/5ae04af4-72b9-4696-81cb-1644cdcd2d29.jpg</banner>
    <banner desc='' id='6' title='我们新增了一个常用导航Tab~'>http://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png</banner>
    <banner desc='一起来做个App吧' id='10' title='一起来做个App吧'>http://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png</banner>
    <banner desc='' id='7' title='送你一个暖心的Mock API工具'>http://www.wanandroid.com/blogimgs/ffb61454-e0d2-46e7-bc9b-4f359061ae20.png</banner>
    <banner desc='' id='4' title='看看别人的面经,搞定面试~'>http://www.wanandroid.com/blogimgs/ab17e8f9-6b79-450b-8079-0f2287eb6f0f.png</banner>
    <banner desc='' id='3' title='兄弟,要不要挑个项目学习下?'>http://www.wanandroid.com/blogimgs/fb0ea461-e00a-482b-814f-4faca5761427.png</banner>
    <banner desc='加个友情链接吧~' id='11' title='加个友情链接吧~'>http://www.wanandroid.com/blogimgs/84810df6-adf1-45bc-b3e2-294fa4e95005.png</banner>
    <banner desc='' id='2' title='JSON工具'>http://www.wanandroid.com/blogimgs/90cf8c40-9489-4f9d-8936-02c9ebae31f0.png</banner>
    <banner desc='' id='5' title='微信文章合集'>http://www.wanandroid.com/blogimgs/acc23063-1884-4925-bdf8-0b0364a7243e.png</banner>
  </data>
</ResponseData>\
'''
def xmlSluper = new XmlSlurper()
// 返回的就是根节点 ResponseData
def xmlResponse = xmlSluper.parseText(xmlStr)
println xmlResponse.getClass() // class groovy.util.slurpersupport.NodeChild
println xmlResponse.errorCode
println xmlResponse.data.banner[0].@desc // 取属性用 @ 开头
println xmlResponse.data.banner[0].text() // 取值用 text()
println '------------------------------------------------------------------'

def titleList = []
xmlResponse.data.banner.each { banner ->
    if (banner.@id.text().contains('3')) {
        titleList.add(banner.@title.text())
    }
}
println titleList.toListString()

println '------------------ 深度遍历 xml 数据 ------------------'
// 不 collect 时拿到的是最里面子结点的文本
def contentList = xmlResponse.depthFirst().findAll { banner -> banner.@id.text().contains('3') }
println contentList.toListString()
// 单引号里两个星号也表示深度遍历
println xmlResponse.'**'.findAll { banner -> banner.@id.text().contains('3') }
println xmlResponse.'**'.find { banner -> banner.@id.text().contains('3') }.@title

titleList = xmlResponse.depthFirst().findAll { banner ->
    banner.@id.text().contains('3')
}.collect { banner ->
    return banner.@title.text()
}
println titleList

println '------------------ 广度遍历 xml 数据 ------------------'
titleList = xmlResponse.data.children().findAll { banner ->
    banner.@id.text().contains('3')
}.collect { banner ->
    return banner.@title.text()
}
println titleList
// 单引号里两个星号也表示广度遍历
println xmlResponse.data.'*'.findAll { banner ->
    banner.@id.text().contains('3')
}.collect { banner ->
    return banner.@title.text()
}
bingoogolapple commented 6 years ago

文件操作

import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder

def test1() {
    def file = new File("WanAndroidBanner.json")
//file.eachLine {
//    println it
//}

//println file.readLines()

    println file.text
}
//test1()

def test2() {
    def file = new File("WanAndroidBanner.json")
    // 读取文件部分内容。Groovy 已经在内部关闭了流,开发者不需要在外面再次关闭
    def reader = file.withReader { reader ->
        char[] buffer = new char[100]
        reader.read(buffer)
        return buffer
    }
    println reader
}
//test2()

def copy(String sourcePath, String destPath) {
    try {
        def destFile = new File(destPath)
        if (!destFile.exists()) {
            destFile.createNewFile()
        }
        new File(sourcePath).withReader { reader ->
            def lines = reader.readLines()
            destFile.withWriter { writer ->
                lines.each { line ->
                    writer.append(line + "\r\n")
                }
            }
        }
        return true
    } catch (Exception e) {
        e.printStackTrace()
    }
    return false
}

def test3() {
    copy('WanAndroidBanner.json', 'WanAndroidBanner2.json')
    println new File('WanAndroidBanner2.json').text
    new File('WanAndroidBanner2.json').deleteOnExit()
}
//test3()

def saveObject(Object obj, String destPath) {
    try {
        def destFile = new File(destPath)
        if (!destFile.exists()) {
            destFile.createNewFile()
        }
        destFile.withObjectOutputStream { ObjectOutputStream out ->
            out.writeObject(obj)
        }
        return true
    } catch (Exception e) {
        e.printStackTrace()
        return false
    }
    return false
}

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) {
        e.printStackTrace()
    }
    return obj
}

def test4() {
    def filePath = 'person.bin'
    def person = new Person(name: 'BGA', age: 26)
    saveObject(person, filePath)

    def result = (Person) readObject(filePath)
    println "the name is ${result.name} and the age is ${result.age}"

    new File(filePath).deleteOnExit()
}
//test4()

def writeXml() {
    def responseText = 'http://www.wanandroid.com/banner/json'.toURL().text
    def responseJson = new JsonSlurper().parseText(responseText)

    new File('WanAndroidBanner.xml').withWriter { writer ->
        // 用来生成 xml 数据的核心类
        def xmlBuilder = new MarkupBuilder(writer)
        //根结点 ResponseData 创建成功
        xmlBuilder.ResponseData() {
            errorCode(responseJson.errorCode)
            errorMsg(responseJson.errorMsg)
            data() {
                responseJson.data.each {
                    banner(desc: it.desc, id: it.id, title: it.title, it.imagePath)
                }
            }
        }
    }
}

writeXml()