Gradle无法将sysout写入文件-java.io.IOException:无法删除文件 [英] Gradle unable to write sysout to file - java.io.IOException: Unable to delete file

查看:277
本文介绍了Gradle无法将sysout写入文件-java.io.IOException:无法删除文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将命令的输出放到某些文件中.在写入文件之前,我要删除文件,然后执行写入操作.这是我的gradle脚本

I am trying to put output of a command to some file. Before writing the file i want to delete the file and than do write operation. Here is my gradle script


group 'org.example'
version '1.0-SNAPSHOT'

task deletefiles(type: Delete){
    delete "$projectDir/somefile.txt"
}

task writefile(type: Exec, dependsOn: deletefiles){
    commandLine 'echo', "Hello World"
    standardOutput = new FileOutputStream("$projectDir/somefile.txt")
}

但是当我运行writefile任务时,出现错误

But when i run writefile tasks , I get below error

Execution failed for task ':deletefiles'.
> java.io.IOException: Unable to delete file 'D:\workspace\code\repo\sample-gradle-mono\somefile.txt'

你知道怎么了吗?

我想的一件事是gradle在 deletefiles 任务开始之前就以某种方式获得了文件锁定.如果是这样,我们如何实现呢?

One thing i guess is that gradle is somehow acquiring lock on file before deletefiles tasks could start. If that is the case, How can we achieve this?

环境信息-

------------------------------------------------------------
Gradle 6.3
------------------------------------------------------------

Build time:   2020-03-24 19:52:07 UTC
Revision:     bacd40b727b0130eeac8855ae3f9fd9a0b207c60

Kotlin:       1.3.70
Groovy:       2.5.10
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          11.0.4 (Oracle Corporation 11.0.4+11)
OS:           Windows 10 10.0 amd64

推荐答案

问题在于,在项目配置阶段,以下代码行已执行

the problem that in your gradle the following line executed at project configuration phase

standardOutput = new FileOutputStream("$projectDir/somefile.txt")

这意味着即使没有启动任何gradle任务,流也已创建并锁定了文件.

it means that stream is created and file locked even before any gradle task was started..

尝试使用这种常规配置来查看问题:

try this groovy configuration to see the issue:


class MyStream extends FileOutputStream{
    MyStream(String f){ 
        super(f)
        println "write $f stream created" 
    }
}

task deletefiles(type: Delete){
    println "delete init"
    doFirst{
        println "delete doFirst" //triggered just before deletion
    }
    delete "out.txt"
}

task writefile(type: Exec, dependsOn: deletefiles){
    println "write init"
    commandLine 'cmd', '/C', 'echo', "Hello World"
    standardOutput = new MyStream("out.txt")
}

在输出中,您可以看到流是在任务执行之前创建的:

in output you can see that stream is created before tasks execution:

cmd> gradle writeFile

> Configure project :
delete init
write init
write out.txt stream created

> Task :deletefiles FAILED
delete doFirst

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':deletefiles'.
> java.io.IOException: Unable to delete file 'out.txt'


要对其进行修复-在"Exec"命令之前定义standardOutput任务已执行:


To fix it - define the standardOutput just before the "Exec" task is executed:

class MyStream extends FileOutputStream{
    MyStream(String f){ 
        super(f)
        println "write $f stream created" 
    }
}

task deletefiles(type: Delete){
    println "delete init"
    doFirst{
        println "delete doFirst"
    }
    delete "out.txt"
}

task writefile(type: Exec, dependsOn: deletefiles){
    println "write init"
    commandLine 'cmd', '/C', 'echo', "Hello World"
    doFirst{
        println "write doFirst"
        standardOutput = new MyStream("out.txt")
    }
    doLast{
        println "write doLast"
    }
}

输出:

cmd>gradle writeFile

> Configure project :
delete init
write init

> Task :deletefiles
delete doFirst

> Task :writefile
write doFirst
write out.txt stream created
write doLast

BUILD SUCCESSFUL in 3s
2 actionable tasks: 2 executed


添加一些明晰性:

例如此任务定义

task writefile(type: Exec, dependsOn: deletefiles){
    println "write init"
    commandLine 'cmd', '/C', 'echo', "Hello World"
    doFirst{
        println "write doFirst"
        standardOutput = new MyStream("out.txt")
    }
    doLast{
        println "write doLast"
    }
}

您可以在gradle中替换为以下常规代码:

you could replace with the following groovy code in your gradle:

def writefile = project.task( [type: Exec, dependsOn: deletefiles], 'writeFile' )

println "write init"
writefile.setCommandLine( ['cmd', '/C', 'echo', "Hello World"] )

writefile.getActions().add( 0, {
    //those commands will be executed later when task `writefile` decided to be executed by gradle
    println "write doFirst"
    writefile.standardOutput = new FileOutputStream("out.txt")
} as Action)

writefile.getActions().add( {
    //those commands will be executed later when task `writefile` decided to be executed by gradle
    println "write doLast" 
} as Action)


指向可能解释此行为的官方文档的链接:


links to official documentation that could explain this behavior:

https://docs.gradle.org/current/userguide /build_lifecycle.html#sec:settings_file

https://docs.gradle.org/current/userguide/more_about_tasks.html

这篇关于Gradle无法将sysout写入文件-java.io.IOException:无法删除文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆