玩转Gradle构建工具(三)、文件操作

378 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

前言

本系列目录

  1. Task
  2. Project、Task常用API
  3. 文件操作
  4. 依赖管理
  5. 多模块构建
  6. 插件编写
  7. SpringBoot插件源码分析
  8. 过度到Kotlin

我们大部分时候都在操作文件,比如打包jar、war的时候,所以这篇文章来单独说一下对文件的常用操作。

file

file是Project提供的方法,用来创建一个文件对象,当然你也可以使用new File(""),但这样显得多余,就像Kotlin,已经去掉了new关键字。

使用file时候,不止可以传入字符型的路径,还可以传入URI、URL,URL也仅仅可以是file:

file函数返回File对象,和我们在java中操作是一样的,就不说了。

文件常用操作

创建目录

task taskA{
    doLast {
        mkdir("app")
    }
}

移动文件

在官网明确的说了Gradle没有用于移动文件和目录的API,但可以使用Apache Ant做到这一点,如下

task taskA{
    doLast {
        ant.move file: "/home/HouXinLin/test/a.txt",
                todir: "./"
    }
}

也可以用Java提供的方法移动。

删除文件

task taskA{
    doLast {
        delete "/home/HouXinLin/test/a.txt"
    }
}

创建文件

task taskA{
    doLast {
        file("/home/HouXinLin/test/a.txt").createNewFile()
    }
}

复制文件

其中layout.buildDirectory.asFile.get()表示获取项目的构建文件路径,当然还有个projectDirectory用于获取项目的跟路径。

task taskA{
    doLast {
        copy {
            from(file("/home/HouXinLin/test/a.txt"))
            into(layout.buildDirectory.asFile.get())
        }
    }
}

from函数由CopySpec提供,源可不单单是File对象,还可以是由files创建的一个文件集合。

task taskA{
    doLast {
        copy {
            from(files("/home/HouXinLin/test/a.txt","/home/HouXinLin/test/test.sh"))
            into("./test")
        }
    }
}

但如果是个目录的话,会全部复制过来,如果需要过滤,可以使用exclude进行排除,如下,只复制源路径下所有文件(排除目录)到目标文件夹。

task taskA{
    doLast {
        copy {
            from("/home/HouXinLin/test/"){
                exclude {
                    it.getFile().isFile()
                }
            }
            into("./test")
        }
    }
}

也可以使用include做一个"只包含",如下,用于复制源路径下只以.jar结尾文件到目标目录。

task taskA{
    doLast {
        copy {
            from("/home/HouXinLin/test/"){
                include("*.jar")
            }
            into("./test")
        }
    }
}

同样可以在复制时重复名,rename有个重载的方法,是一个闭包,在闭包中需要返回一个新的文件名,如果返回null,则表示使用原来的,在这个闭包中使用it表示获取当前预要重复名的文件名称。

task taskA{
    doLast {
        def count =0
        copy {
            from("/home/HouXinLin/test/"){
                rename {
                    count++
                   return count+".jar"
                }
                include("*.jar")
            }
            into("./test")
        }
    }
}

同时还支持在复制每个文件时,进行一个回调,如下,通过eachFile增加一个回调,在Gradle复制时,会依次把要复制的文件回调到这里。

task taskA{
    doLast {
        copy {
            from("/home/HouXinLin/test/"){
                eachFile {
                    println(it)
                }
                include("*.jar")
            }
            into("./test")
        }
    }
}

遍历目录

task taskA{
    doLast {
       file("/home/HouXinLin/test/").listFiles().each{
           println(it)
       }
    }
}

但这个方式不会更深层次遍历,如果要深层次遍历,可以使用下面这种方式。

task taskA{
    doLast {
        Files.walkFileTree(Paths.get("/home/HouXinLin/test/"),new SimpleFileVisitor<java.nio.file.Path>(){
            @Override
            FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException {
                println(file)
                return super.visitFile(file, attrs)
            }
        })
    }
}

不知道Gradle有没有提供相关接口,我没有找到。

创建归档

如要把构建目录创建成一个zip文件。

tasks.register('testTask', Zip) {
    from(layout.buildDirectory.asFile.get())
    destinationDir = file("./")
    archiveName = "test.zip"
}

解压归档

由于zip中是由多个文件组成,所以要使用zipTree函数先去解析成一个FileTree。

tasks.register('unpackFiles', Copy) {
    from zipTree("./test.zip")
    into layout.buildDirectory.dir("resources")
}

创建jar

这个可以使用一个插件,也可以手动创建,如果你熟悉jar命令的话,下面作为一个演示,更多情况我们都会使用插件来打包。

task buildJar {
    mkdir("jar")
    copy {
        from(layout.buildDirectory.dir("classes/java/main"))
        into("./jar")
    }
    Files.write(Paths.get(layout.projectDirectory.file("jar/MANIFEST.MF").asFile.absolutePath),"Main-Class: gradle.test.App\r".getBytes())
    copy {
        from(layout.projectDirectory.file("MANIFEST.MF"))
        into(layout.projectDirectory.file("app/jar"))
    }
    this.exec {
        workingDir("./jar")
        executable("jar")
        args("-cvfe" ,"test.jar", "gradle.test.App" ,"./")
    }
}

下面是使用插件,插件我们在后面说。

plugins {
    id 'java'
}
tasks.jar{
    manifest {
        attributes( "Main-Class": "gradle.test.App")
    }
}

还有一个application插件也可以打包,他的installDist任务用于安装程序,他打包出来的jar需要一个脚本启动,就类似启动tomcat那样,用的不多。

plugins {
    id 'application'
}
application{
    mainClass="gradle.test.App"
}