9

I have been trying to delete a file in windows operating system using the Java IO file.delete() API. However it fails and returns false. The same code works like a charm in Ubuntu.

I have verified that the permissions of the file allows the program to delete it. Also all the input and output stream for the file has been opened as try with resources.

try (InputStream in = new FileInputStream(localFile); OutputStream out = new FileOutputStream(destinationFileName))

Using a debugger I have tested and found out that at the code line that I delete the file it returns true for following API calls.

file.exists()
file.canRead();
file.canWrite();
file.canExecute();

I have even tried adding System.gc() right before calling delete to make sure all the streams are closed.

Not sure whether this is helpful information but I have even tried using the Apache commons FileUtils.forceDelete(file) method and it has also been failed.

So what am I missing here?

Update:

By using Files.delete(Paths.get(file.getAbsolutePath())) I got the following error.

java.nio.file.FileSystemException: C:\Users\thuvvareka\Desktop\temp\in\sd.xml: The process cannot access the file because it is being used by another process.
    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
    at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
    at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
    at java.nio.file.Files.delete(Files.java:1126)
    at org.adroitlogic.x.transport.file.FileMessageInjector.finalizeProcessing(FileMessageInjector.java:161)
    at org.adroitlogic.x.transport.file.FileMessageInjector.afterProcess(FileMessageInjector.java:123)
    at org.adroitlogic.x.transport.file.FileMessageInjector.afterProcess(FileMessageInjector.java:37)
    at org.adroitlogic.x.base.trp.ScheduledMessageInjector.lambda$2(ScheduledMessageInjector.java:72)
    at org.adroitlogic.x.api.trp.MessageReceiver.lambda$receive$3(MessageReceiver.java:100)
    at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760)
    at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736)
    at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
    at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962)
    at org.adroitlogic.x.core.MessageContext.lambda$createNewResponseFuture$2(MessageContext.java:459)
    at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760)
    at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736)
    at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
    at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962)
    at org.adroitlogic.x.core.MessageContext.completeMessageFlowSuccessfully(MessageContext.java:332)
    at org.adroitlogic.x.base.connector.EgressConnectorElement.sendMessage(EgressConnectorElement.java:185)
    at org.adroitlogic.x.base.connector.EgressConnectorElement.process(EgressConnectorElement.java:146)
    at org.adroitlogic.x.base.processor.AbstractProcessingElement.processMessage(AbstractProcessingElement.java:103)
    at org.adroitlogic.x.base.processor.TraceableProcessingElement.processMessage(TraceableProcessingElement.java:53)
    at org.adroitlogic.x.base.connector.IngressConnectorElement.receiveMessage(IngressConnectorElement.java:119)
    at org.adroitlogic.x.core.IntegrationPlatform.lambda$receive$0(IntegrationPlatform.java:81)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
dammina
  • 655
  • 1
  • 8
  • 23
  • File.delete() is quite old API. You could try to use `Files.delete(somePath)`, so maybe you get a better error/exception: see http://stackoverflow.com/questions/12139482/difference-between-filesdeletepath-and-filedelete – user140547 Nov 20 '16 at 16:24
  • I have updated the question with the exception that I got. – dammina Nov 20 '16 at 16:39
  • On Windows you cannot delete a file where anybody (including your own process) has a file handle open. This is different from Unix where you can always delete it (and even use the open file descriptors afterwards). What you can do (if it is a temp file which should be deleted) you can use deleteOnExit, this might work as long as your process is the only one having open filedescriptors. – eckes Nov 20 '16 at 16:41
  • @eckes however I have tried using the following simple code snippet and it has successfully deleted the file. `File file = new File("C:\\Users\\thuvvareka\\Desktop\\temp\\in\\sd.xml"); try (FileInputStream fis = new FileInputStream(file)){ System.out.println(fis.getChannel().size()); } catch (IOException e){ e.printStackTrace(); } System.out.println(file.delete());` **output:** '0 true' – dammina Nov 20 '16 at 16:51
  • Yes in your sample the file is closed before it gets deleted. – eckes Nov 20 '16 at 17:04
  • same happens in the actual code that I run. – dammina Nov 20 '16 at 17:06
  • The file could be open from other streams. You did not show your code so its hard to guess, but from the Exception it looks like you do that in the middle of a `stream()` processing, there are a lot of possible wrong assumptions about that. – eckes Nov 20 '16 at 17:06

5 Answers5

3

Welcome to Windows.

java.nio.file.FileSystemException: C:\Users\thuvvareka\Desktop\temp\in\sd.xml: 
The process cannot access the file because it is being used by another process.

Typically, when a process has a file open in Windows, the operating system locks the file in a way that the file cannot be deleted. If it's your program that has the file open while you are trying to delete it, then close the file first and then delete it. If it's another program that has the file open, then you'll need to figure out who has it open and go from there.

When a process has a file open in Linux, there is typically nothing preventing you from deleting it, which is why you see different behavior.

BillRobertson42
  • 12,602
  • 4
  • 40
  • 57
3

I ran into this recently. I created a workaround where if file.delete() returns false I check if file.exists() returns true and if so, I wait a bit then try again and give up after some number of tries.

My unproven suspicion is that virus checkers on Windows lock the file to examine the file and waiting allows the virus checker to finish.

            // Remove the original file.
            if(!file.delete()) {
                // wait a bit then retry on Windows
                if (file.exists())
                {
                    for (int i = 0; i < 6; i++)
                    {
                        Thread.sleep(500);
                        System.gc();
                        if (file.delete())
                           break;
                    }
Alex Harui
  • 106
  • 5
1

Use Files.delete(filePath) instead of file.delete() as file.delete() has some issue regarding permission on windows.

Md Samiul Alim Sakib
  • 1,114
  • 12
  • 15
  • 1
    There is no differences between the two APIs for this case. – eckes Nov 20 '16 at 16:41
  • It says your file is opened in JVM. Please try closing the file and try again as a File opened by JVM couldn't be deleted. Hope it will help. – Md Samiul Alim Sakib Nov 20 '16 at 16:44
  • @SakibSami what do you mean by closing the file. Java try with resources verifies that all the resources (file streams) will be closed with the try clause. – dammina Nov 20 '16 at 16:47
0

I had the same issue. Do out.close(); solve it.

System.gc() will not remove link to the OutputStream as long as you don't have close it.

Hydrolien
  • 36
  • 4
-1

Maybe you can use System.Runtime.exec() to run a terminal / command line command to delete a specific file. This may be somehow platform dependent, but the command to be entered to the exec() function may differ among os properties.

You can check this thread to determine the current os of the java program running.

How do I programmatically determine operating system in Java?

In linux, your line would be as follows:

System.Runtime.exec("rm <path to file>");
Community
  • 1
  • 1
fercis
  • 611
  • 2
  • 12
  • 26