0

In some place I create temporary file:

Files.createTempDirectory("chunk");

In some other place after processsing, I try to delete file:

Files.deleteIfExists(somePath) 

and experience following trace:

java.nio.file.FileSystemException: C:\....\Temp\chunk11607697185854596263\chunk-3.csv: The process cannot access the file because it is being used by another process.
    at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92)
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
        at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:270)
        at java.base/sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:110)
        at java.base/java.nio.file.Files.deleteIfExists(Files.java:1180)
        at my.some.project.batch.MyClass.afterStep(MyClass.java:31)

It happens when I start application on my local Windows mashine and doesn't happen in docker. Also I don't experience such error when I run application locally on MacOS. What the problem and how can I fix it ?

gstackoverflow
  • 34,819
  • 98
  • 304
  • 641
  • Check which process has the file open with [Process Explorer](https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer). Perhaps you have opened the file with Notepad or something else to check the file and not closed it? – Roger Gustavsson Sep 06 '19 at 11:30
  • 1
    Make sure your code is closing all InputStreams, OutputStreams, Readers, and Writers. – VGR Sep 06 '19 at 12:00
  • @VGR I provided all code related to IO – gstackoverflow Sep 06 '19 at 12:06
  • When I re-read your question, your error message and your explanation of what you are doing doesn't add up with your code. You create a directory, do some stuff and then delete... what exactly? Is `somePath` the path returned by `createTempDirectory`? To delete a directory the directory must be empty. However, the error message points to a file in that directory. Can you create a [Minimal, reproducable example](https://stackoverflow.com/help/minimal-reproducible-example)? Either you will find the error yourself, or it will be easier for us to understand what's going on. – Roger Gustavsson Sep 06 '19 at 12:31
  • “all code related to IO”? Are you saying there are no other lines of code that make use of the temporary directory you created? If that’s the case, why create it in the first place? – VGR Sep 06 '19 at 13:26

2 Answers2

0

Check that the file isn't opened by some other process. This check can be done with Process Explorer. When you have started the program, select Find in the menu and then Find Handle or DLL..., or press Ctrl+F. Enter the name of the file that is being locked by some process and click Search.

There's a difference between Windows and Unix-like operating systems regarding the handling of removal of opened files.

On Unix-like systems a file can be removed even if it's opened by other processes. The actual file is not removed until all other processes has closed the file, but the filename entry on the filesystem is removed. The low-level file remove operation returns success as soon as the first part of the operation succeeds. Removal of the actual file data is delayed until the open count has reached 0.

On Windows the file may not be opened by any process for the low-level file remove operation to be able to succeed.

This could be a reason why you see a different behaviour when running your program on Windows versus Docker or MacOS.

Roger Gustavsson
  • 1,659
  • 10
  • 20
  • Could you explain how to find process which holds the file using tool you suggested? – gstackoverflow Sep 06 '19 at 11:55
  • Actually I create and remove file within the same process – gstackoverflow Sep 06 '19 at 12:01
  • But is it opened by some external process as well? Or, as @VGR suggests in a comment to your question above, have you closed all kind of streams that you have used for writing and/or reading? – Roger Gustavsson Sep 06 '19 at 12:04
  • Other external process don't know anything about these files – gstackoverflow Sep 06 '19 at 12:07
  • After I start search in your tool - my computer start to work extremely slow – gstackoverflow Sep 06 '19 at 12:08
  • http://dl3.joxi.net/drive/2019/09/06/0005/3037/338909/09/712d3ee07d.jpg – gstackoverflow Sep 06 '19 at 14:18
  • The error message is misleading. Shared file access has nothing inherently to do with other processes. Windows allows a file-system file or directory to be opened for delete access (for unlinking or renaming a file) if all existing opens share delete access, regardless of the processes involved. It's failing because "chunk-3.csv" is open somewhere without delete sharing. Even if allowed and the delete succeeds, Windows won't actually unlink the file from the directory until all open references to it are closed -- not unless we use the new POSIX-semantics delete in Windows 10 (undocumented). – Eryk Sun Sep 06 '19 at 21:36
0

There are quite a few problems around when file is deleted with Java in Windows. The most important thing is to really make sure there are no unclosed streams before trying to delete a file as VGR already mentioned.

For more info about the usual problems you could take a look at this: delete & GC and this: file delete

I am using this kind of awful looking "solution" for deleting files, feel free to try:

public static boolean deleteFile(File file)
        throws Exception {
    if (!file.exists()) {
        throw new Exception("File not found: " + file.getName());
    }
    try {
        file.setWritable(true);
    } catch (Exception ignored) {
    }
    int delay = 50;
    for (int i = 0; i < 20; i++) {
        if (file.delete()) {
            return true;
        }
        System.gc();
        try {
            Thread.sleep(delay);
        } catch (InterruptedException ignored) {
        }
        delay = delay + 50;
    }
    throw new Exception("Could not delete the file '"
            + file.getName() + "'");
}
Jokkeri
  • 901
  • 1
  • 11
  • 30