1、object对象
1.1、查看object对象的信息
-
/** * @author liangchen* @date 2020/11/22 */ // 使用 dump 和inspect 方法 def newline = "\n" assert newline.toString() == "\n" // dump 对象信息 assert newline.dump()=="<java.lang.String@a value=\n hash=10>" // 值 assert newline.inspect() == /'\n'/ class MyClass{ def first = 1 def getSecond(){ first * 2 } public third = 3 def myMethod(){} } def obj = new MyClass() //判断是否存在某个属性 assert obj.hasProperty('first') // 判断是否存在某个方法 assert obj.respondsTo('myMethod') // 属性的key def keys = ['first', 'second', 'class'] assert obj.properties.keySet() == new HashSet<>(keys) // 属性map获取属性 assert 1 == obj.properties['first'] assert 1 == obj.properties.first // 调用getAt('first') assert 1 == obj.first assert 1 == obj['first'] def one = 'first' def two = 'second' obj[one] = obj[two] // 查找存在first=2字符串 assert obj.dump() =~'first=2'
1.2、Object方便使用的方法
-
基础用法
-
package com.jack.groovy.ch12 import com.jack.groovy.ch7.Address /** * @author liangchen* @date 2020/11/22 */ // 在java中,判断相等 int a = 1; int b =1; assert a == b // 在groovy中 assert a.is(b) // switch 也不限于Integer char 类型 switch (new Date(0)) { case new Date(0): println 'dates are equal' } new Date().identity { println "$date.$month.$year" } //赋值 def address = new Address() address.with { state = '中国' street = '天顶乡' } // 格式化打印 printf('PI=%2.5f and E = %2.5f', Math.PI, Math.E) //直接use类的静态方法 class StringCasingCategory{ static String lower(String string) { return string.toLowerCase() } } use(StringCasingCategory){ assert "groovy" == "GROOvy".lower() } // sleep 打印 text = "间断打印" for (c in text) { sleep(100) print c }
-
1.3、遍历迭代
2、文件和I/O
/**
* @author liangchen* @date 2020/11/22
*/
file = new File('_12_1_1InteractiveObject.groovy')
file.each {println it}
assert file.any{ it=~ /方法/}
assert 2 == file.findAll { it =~ /方法/ }.size()
assert 38== file.grep{it}.size()
2.1、遍历文件系统
-
package com.jack.groovy.ch12 import groovy.io.FileType /** * @author liangchen* @date 2020/11/22 */ file = new File('.') // 打印文件名 println file.name // 绝对路径 println file.absolutePath // 规范路径 println file.canonicalPath // 是否为目录 println file.directory // File 遍历系统 def topDir = new File('../../../../') def srcDir = new File(topDir,'') dirs = [] srcDir.eachDir { dirs << it.name } assert ['com'] == dirs dirs=[] // 递归遍历文件夹 topDir.eachDirRecurse {dirs << it.name} assert dirs.containsAll(['jack','groovy', 'ch2']) dirs = [] // 匹配第一个 topDir.eachDirMatch(~/[^1]*/) { dirs << it.name } assert dirs == ['com'] // 遍历文件和目录 files=[] topDir.eachFile { files << it.name } assert files.contains('com') assert files.contains('.DS_Store') files = [] topDir.eachFile ( FileType.FILES){files << it.name} assert files.contains('.DS_Store') // 计数目录 count = 0 srcDir.eachFileRecurse {if(it.directory) count++} count =0 srcDir.eachFileRecurse (FileType.DIRECTORIES) {count++} assert 19 == count topDir.eachFileMatch(~/_12_2_1.*/) { files << it.name } assert ['.DS_Store'] == files
2.2、读取输入
/**
* @author liangchen* @date 2020/11/22
*/
example = new File("data/example.txt")
lines = ['line one', 'line two', 'line three']
assert lines == example.readLines()
example.eachLine {
assert it.startsWith('line')
}
hex = []
example.eachByte {hex << it}
assert hex.size() == example.length()
example.splitEachLine(/\s/){
assert 'line' == it[0]
}
example.withReader {reader->
assert 'line one' == reader.readLine()
}
2.3、写出文件
-
reader 做writer
-
/** * 写出文件 * @author liangchen* @date 2020/11/22 */ def outFile = new File('data/example.txt') def lines = ['line one', 'line two', 'line three'] outFile.write(lines[0..1].join("\n")) outFile.append("\n" + lines[2]) assert lines == outFile.readLines() outFile.withWriter {writer -> writer.writeLine(lines[0]) } outFile.withWriterAppend ('ISO8859-1') { writer -> writer << lines[1] << "\n" } outFile << lines[2] TimeZone.default = TimeZone.getTimeZone("CET") reader = new StringReader('abc') writer = new StringWriter() writer << "\nsome String" << "\n" writer << [a: 1, b: 2] << "\n" writer << [3, 4] << "\n" writer << new Date(0) << "\n" // ready可直接做writer入参 writer << reader << "\n" println writer.toString()
-
2.4、过滤和转换
-
new Reader / new InputStream / new DataInputStream / newDataOutputStream/new ObjectOutputStream/ new OutputStream/new Writer 获取资源
-
package com.jack.groovy.ch12 /** * 过滤行数 * @author liangchen* @date 2020/11/23 */ def n = System.lineSeparator() reader = new StringReader("abc") writer = new StringWriter() //当前元素的下一个元素 reader.transformChar(writer){it.next()} assert 'bcd' == writer.toString() // 去掉 line字段 reader = new File("data/example.txt").newReader() writer = new StringWriter() reader.transformLine(writer) { it - 'line' } assert " one${n} two${n} three${n}" == writer.toString() input = new File('data/example.txt') writer = new StringWriter() // 匹配有one字符串的行 input.filterLine(writer) { it =~ /one/ } assert "line one${n}" == writer.toString() // 过滤长度大于8 的行数 writer = new StringWriter() writer << input.filterLine {it.size() > 8} assert "line three${n}" == writer.toString() // base 64 byte[] data = new byte[256] for(i in 0..255) { data[i] == i } store = data.encodeBase64().toString() // 以什么开头 assert store.startsWith('AAECAWQFBg') // 以。。结尾 assert store.endsWith ('r7/P3+/w==') //解码base64 restored = store.decodeBase64() assert data.toList() == restored.toList()
- 注意需要了解base64 参考RFC 2045
2.5、Streaming serialized objects(流序列化对象)
-
/** * @author liangchen* @date 2020/11/24 */ // 序列化 file = new File('objects.dat') // 在jvm退出时候删除文件 file.deleteOnExit() objects = [1,'Hello Groovy!', new Date()] // 写入对象到文件中 file.withObjectOutputStream { outstream -> objects.each{ outstream << it } } // 从文件中读取对象到retrieved中 retrieved = [] file.withObjectInputStream {instream -> instream.eachObject { retrieved << it } } assert retrieved == objects
2.6 临时数据和文件复制
-
// 12.11 在临时目录的复制 // 创建一个临时目录 File tempDir = File.createTempDir() assert tempDir.directorySize() == 0 // 创建一个临时文件input.data, File source = new File(tempDir, 'input.dat') source.bytes = "hello world".bytes // 这个目录下所有文件大小之和 assert tempDir.directorySize() == 11 //创建一个新的文件,output.dat, 把input.dat的内容输出到output.dat中 File destination = new File(tempDir, 'output.dat') destination.withDataOutputStream { os -> source.withDataInputStream {is -> os << is } } // 最后文件大小是 11*2 = 22 assert tempDir.directorySize() == 22 // 删除临时文件夹 tempDir.deleteDir()
3、线程和处理
3.1、groovy多线程
-
package com.jack.groovy.ch12 import java.util.concurrent.BlockingQueue import java.util.concurrent.LinkedBlockingQueue /** * @author liangchen* @date 2020/11/24 */ // Groovy 多线程 //创建线程的方式 // 方式1 t = new Thread(){ // 具体运行内容 } t.start() // 方式2 Thread.start { //具体运行内容 } Thread.start("线程名称"){ } // 创建守护线程 Thread.startDaemon { //具体运行内容 } Thread.startDaemon ("线程名称"){ // 具体运行内容 } // 线程延迟1秒后运行 current = System.currentTimeMillis() println "当前时间:$current" new Timer().runAfter(1000){ delta = System.currentTimeMillis() - current println "耗时:$delta" } // 12.12 使用线程来解决生产者和消费者 //在Thread中定义个静态的getName方法 Thread.metaClass.'static'.getName = {Thread.currentThread().name} BlockingQueue sharedQueue = [] as LinkedBlockingQueue // 创建生产者线程 Thread.start('push'){ // 遍历10次 10.times { try { println("${Thread.name}\t: ${it}") // 数字加到sharedQueue当中 sharedQueue << it sleep(100) } catch (InterruptedException ignore) {} } } // 创建消费者线程 Thread.start('pop') { for (i in 0..9) { sleep 200 println("队列元素:$sharedQueue") println ("${Thread.name}\t : ${sharedQueue.take()}") } }
3.2、整合外部过程(执行命令行)
-
package com.jack.groovy.ch12 /** * @author liangchen* @date 2020/11/24 */ // // 用groovy执行命令行的命令, 创建一个process, 也就是可以创建一个执行过程 def listFiles = 'ls'.execute() // 这里创建一个文件夹aa 'mkdir aa'.execute() def ignoreCase = "tr '[A-Z]' '[a-z]'".execute() def reverseSort = 'sort -r'.execute() println listFiles listFiles | ignoreCase| reverseSort reverseSort.waitForOrKill(1000) if (reverseSort.exitValue()) { println reverseSort.err.text }each { println reverseSort.text } // 发现list def outputBuffer = new StringBuffer() def errorBuffer = new StringBuffer() zipProcess = 'gzip -c'.execute() unzipProcess = 'gunzip -c'.execute() unzipProcess.consumeProcessOutput(outputBuffer,errorBuffer) zipProcess.consumeProcessErrorStream(errorBuffer) zipProcess | unzipProcess zipProcess.withWriter { writer-> writer << 'Hello World' } unzipProcess.waitForOrKill(1000) println 'outPut:' + outputBuffer println 'Error:' + errorBuffer
4、 模板
4.1、理解模板格式
- 模板格式
4.2、模板实战
-
${} 对应不是迭代的, <% %> 迭代情况拼接字符串
-
package com.jack.groovy.ch12 import groovy.text.SimpleTemplateEngine /** * @author liangchen* @date 2020/11/24 */ //注意是三单引号 ${} 对应不是迭代的, <% %> 迭代情况拼接字符串 mailReminder = ''' Dear ${salutation?salutation+' ':''}$lastname,another month has passed and it's time for these <%=tasks.size()%> tasks:<% tasks.each{%>- $it<%} %> your collaboration is very much appreciated ''' // 创建模板引擎, def engine = new SimpleTemplateEngine() // 创建模板 def template = engine.createTemplate(mailReminder) // 创建绑定数据 def binding = [ salutation:'Mrs.', lastname:'Davis', tasks :['visit the Groovy in Action (GinA) page', 'chat with GinA readers'] ] // 进行绑定 println template.make(binding).toString()
4.3、高级template特性
- 需要使用单引号,因为双引号GString在编译时候自动替换值,而模板是需要在调用绑定方法时候才替换,所有双引号会报方法找不到异常
- StreamingTemplateEngine :处理template比较大,一般大于64000个字符
- GStringTemplateEngine: 在写闭包中提供更好性能和扩展能力
- XmlTemplateEngine 处理xml文件
- MarkupTemplateEngine: 推荐使用,编译模板有更好的性能,检查在模板中使用的属性
5、Groovlets
- 暂时不涉及
6、总结
- GDK 加强JDK的能力
- GDK使得处理I/O更加简单,自动处理资源的释放
- GDK使用线程也是比较简单