Java open file streams in one class and close / delete file in another class

I want to delete a file that is open and executed but not closed. See the code below:

Class A (cannot be changed):

import java.io.FileOutputStream;

public class A {

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

    }
}

      

Class 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()));

    }

}

      

In class A, just open the stream without closing the file. In class B, call the startup method and then try to delete the file. Since the file is still open. I cannot delete the file.

Error: The process cannot access the file because it is being used by another process.

Actual scenario: We load the jars dynamically. The classes inside the jar create a file. When an exception is thrown, a file is created that is 0 bytes in size. We need to delete this file. Since the file is not closed during the exception, we cannot delete the file.

We could fix the problem if we could close the streams in the jar classes, but we cannot modify the jars that create the files as they are client specific jars.

Please suggest how to delete the open file without changing the code in class A.

+3


source to share


6 answers


Make sure you close the file even if it had an exception.

eg.



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
        }
    }
}

      

0


source


You must close the file before any delete operation, as it is bad practice at first and secondly it will lead to memory leaks.



0


source


If you are using Tomcat, you can set AntiLockingOption and antiJARLocking in $ CATALINA_HOME / conf / context.xml for Windows:

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

      

Important note:

The antiResourceLocking parameter can prevent JSPs from being redeployed if they are edited that requires redeployment.

More about this option: http://tomcat.apache.org/tomcat-7.0-doc/config/context.html

antiResourceLocking:

If true, Tomcat will prevent file locking. This will have a significant impact on application startup times, but allows you to fully deploy and deploy webapp hot to platforms or configurations where file locking can occur. If not specified, the default is false.

0


source


Updated as per OPs comment. Another approach might be to subclass A and override 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");
    }

      

0


source


Pass the resource as a parameter and it will become the caller's responsibility to clean up the resources.

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

      

defiant:

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

      

0


source


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

If you have UAC enabled, you will also need to run java in elevated mode (for example, run command prompt as administrator). Then, assuming the unlock 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 can use "-d"

instead "-s"

and Unlocker will delete the file for you.

0


source







All Articles