Java在一个类中打开文件流,在另一个类中打开/删除文件

时间:2015-06-15 10:02:28

标签: java file stream

我想删除已打开并完成写入但未关闭的文件。请参考以下代码:

A类(不能更改):

import java.io.FileOutputStream;

public class A {

    public void run(String file) throws Exception {
        FileOutputStream s = new FileOutputStream(file);

    }
}

B组:

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class B {

    public static void main(String[] args) throws Exception {
        String path = "D:\\CONFLUX_HOME\\TestClient\\Maps\\test\\newTest.txt";
        A a = new A();
        a.run(path);
        File f = new File(path);
        Files.delete(Paths.get(f.getAbsolutePath()));

    }

}

在A类中,只需打开流而不关闭文件。 在B类中,调用A的run方法然后尝试删除该文件。 由于文件仍然打开。我无法删除该文件。

错误是: 该进程无法访问该文件,因为它正由另一个进程使用。

实际情景是: 我们正在动态加载jar。 jar中的类正在创建文件。当存在异常时,将创建一个文件,其大小为0字节。我们需要删除此文件。由于在异常期间文件未关闭,我们无法删除该文件。

如果我们可以关闭jar类中的流,我们可以解决问题,但是我们无法修改创建文件的jar,因为它们是客户端特定的jar。

请建议如何删除已打开的文件,而不修改A类中的代码。

6 个答案:

答案 0 :(得分:0)

确保关闭文件,即使写入文件时出现异常。

E.g。

public void run(String file) throws Exception {
    FileOutputStream s = null;
    try {
        s = new FileOutputStream(file);    
    } finally {
        try {
            s.close();
        } catch(Exception e) {
            // log this exception
        }
    }
}

答案 1 :(得分:0)

你必须在任何删除操作之前关闭文件,因为它首先是一个不好的做法,其次是它会导致内存泄漏。

答案 2 :(得分:0)

如果您使用的是Tomcat,则可以在Windows的$ CATALINA_HOME / conf / context.xml中设置AntiLockingOption和antiJARLocking:

<Context antiJARLocking="true" antiResourceLocking="true" >

重要提示:

antiResourceLocking选项可以在编辑需要重新部署的JSP时停止重新部署JSP。

详细了解此选项: http://tomcat.apache.org/tomcat-7.0-doc/config/context.html

<强> antiResourceLocking:

如果为true,Tomcat将阻止任何文件锁定。这将显着影响应用程序的启动时间,但允许在可能发生文件锁定的平台或配置上进行完全webapp热部署和取消部署。如果未指定,则默认值为false。

答案 3 :(得分:0)

根据OP评论更新。 另一种方法可能是子类A并覆盖run()

public static void main(String[] args) throws Exception  {
        String path = "D:\\CONFLUX_HOME\\TestClient\\Maps\\test\\newTest.txt";


        A a = new A() {
            @Override
            public void run(String file) throws Exception {
                FileOutputStream s = new FileOutputStream(file);
                s.close();
            }
        };
        a.run(path);

        File f = new File(path);

        Files.delete(Paths.get(f.getAbsolutePath()));
        System.out.println("foo");
    }

答案 4 :(得分:0)

将资源作为参数传递,调用者有责任清理资源

   public void run(FileOutputStream stream) throws Exception {
     ...
   }

来电者:

try(FileStream stream = new FileStream(path)){
      A a = new A();
      a.run(stream);
}catch(Exception e){
  .. exception handling
}

答案 5 :(得分:0)

I don't think you'll find a pure java solution to this problem. One option is to install Unlocker (being careful to hit "Skip" on all the junkware) and invoke it from your code.

If you have UAC enabled, you'll also need to be running your java in an elevated process (e.g. start command prompt as Administrator). Then, assuming unlocker is in C:\Program Files\Unlocker:

Process p = new ProcessBuilder("c:\\Program Files\\Unlocker\\Unlocker.exe",path,"-s").start();
p.waitFor();

And after that you can delete the file as before. Or you could use "-d" instead of "-s" and Unlocker will delete the file for you.

相关问题