file.delete() returns false even though file.exists(), file.canRead(), file.canWrite(), file.canExecute() all return true

181,944

Solution 1

It was pretty odd the trick that worked. The thing is when I have previously read the content of the file, I used BufferedReader. After reading, I closed the buffer.

Meanwhile I switched and now I'm reading the content using FileInputStream. Also after finishing reading I close the stream. And now it's working.

The problem is I don't have the explanation for this.

I don't know BufferedReader and FileOutputStream to be incompatible.

Solution 2

Another bug in Java. I seldom find them, only my second in my 10 year career. This is my solution, as others have mentioned. I have nether used System.gc(). But here, in my case, it is absolutely crucial. Weird? YES!

finally
{
    try
    {
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
        System.gc();
    }
    catch (IOException e)
    {
        logger.error(e.getMessage());
        e.printStackTrace();
    }
}

Solution 3

I tried this simple thing and it seems to be working.

file.setWritable(true);
file.delete();

It works for me.

If this does not work try to run your Java application with sudo if on linux and as administrator when on windows. Just to make sure Java has rights to change the file properties.

Solution 4

Before trying to delete/rename any file, you must ensure that all the readers or writers (for ex: BufferedReader/InputStreamReader/BufferedWriter) are properly closed.

When you try to read/write your data from/to a file, the file is held by the process and not released until the program execution completes. If you want to perform the delete/rename operations before the program ends, then you must use the close() method that comes with the java.io.* classes.

Solution 5

As Jon Skeet commented, you should close your file in the finally {...} block, to ensure that it's always closed. And, instead of swallowing the exceptions with the e.printStackTrace, simply don't catch and add the exception to the method signature. If you can't for any reason, at least do this:

catch(IOException ex) {
    throw new RuntimeException("Error processing file XYZ", ex);
}

Now, question number #2:

What if you do this:

...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...

Would you be able to delete the file?

Also, files are flushed when they're closed. I use IOUtils.closeQuietly(...), so I use the flush method to ensure that the contents of the file are there before I try to close it (IOUtils.closeQuietly doesn't throw exceptions). Something like this:

...
try {
    ...
    to.flush();
} catch(IOException ex) {
    throw new CannotProcessFileException("whatever", ex);
} finally {
    IOUtils.closeQuietly(to);
}

So I know that the contents of the file are in there. As it usually matters to me that the contents of the file are written and not if the file could be closed or not, it really doesn't matter if the file was closed or not. In your case, as it matters, I would recommend closing the file yourself and treating any exceptions according.

Share:
181,944
Jenny Smith
Author by

Jenny Smith

Always try to be better than you think you can be!

Updated on February 20, 2020

Comments

  • Jenny Smith
    Jenny Smith over 4 years

    I'm trying to delete a file, after writing something in it, with FileOutputStream. This is the code I use for writing:

    private void writeContent(File file, String fileContent) {
        FileOutputStream to;
        try {
            to = new FileOutputStream(file);
            to.write(fileContent.getBytes());
            to.flush();
            to.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    As it is seen, I flush and close the stream, but when I try to delete, file.delete() returns false.

    I checked before deletion to see if the file exists, and: file.exists(), file.canRead(), file.canWrite(), file.canExecute() all return true. Just after calling these methods I try file.delete() and returns false.

    Is there anything I've done wrong?

  • Ravi Wallau
    Ravi Wallau almost 15 years
    I would argue it's a bug then: java.sun.com/javase/6/docs/api/java/io/… It says in there that the method should close the stream and any resources associated with it. I usually like to close all the streams in the inverted sequence (the last ones to be open are the first ones to be closed) using IOUtils.closeQuietly, but it tends to be overkill.
  • Jenny Smith
    Jenny Smith almost 15 years
    I tried the first thing - closing the output stream in the finally block. And it didn't work. What did happened if I tried to read after thatm is that I got a message saying the stream was closed. When switching and reading the file with FileInputReader, none of the "bad" thing described above happened.
  • Dave
    Dave over 13 years
    I was having this exact problem I and I thought I was going crazy. Thanks for the solution!
  • David
    David almost 13 years
    It's 2011 with JDK 7 and the problem still isn't fixed. I'm so glad I found this thread - I simply couldn't figure out what was wrong...
  • Deepak Singhal
    Deepak Singhal almost 12 years
    For this problem; generally people talk about setting references as null or calling system.gc(); but for me even after server restart files were not getting deleted !! But file.setWritable(true); just worked..
  • ixM
    ixM about 11 years
    Although I did not open it with any kind of stream (just doing a new File(path)), I encountered the same problem and adding System.gc() before the delete() made it work!
  • marcolopes
    marcolopes about 11 years
    What S.O. do you use? If you can have access to the STREAMS, close them, it will work. But if the file is "already" locked, then, you have a problem.
  • bharal
    bharal almost 11 years
    -1 looping in your code to delete a file isn't a great idea. Why not just use the gc() option that works?
  • etech
    etech almost 11 years
    @bharal Notice I state above that none of the other solutions (including gc()) worked in my particular case. While I agree using a while loop is not ideal, it may be an appropriate solution in certain circumstances. Adding an additional check to the code above, such as a timeout or max iterations variable, would be a good way to make the while loop safer.
  • bharal
    bharal almost 11 years
    @etech if your file never existed though, you've just created an infinite loop.
  • runholen
    runholen almost 10 years
    I had a very annoying problem with a file that I read and closed and then tried to delete. Nothing mentioned here helped. Then after an hour I discovered it was just the file rights, since the file had been created by another user :-D
  • jww
    jww almost 10 years
    Just a stab in the dark... Can you call finalize() to ensure cleanup? Or perhaps set to = null? See Forcing Finalization and Garbage Collection.
  • Rebeccah
    Rebeccah over 9 years
    jww: No, finalize() doesn't ensure cleanup, nor does setting to = null. I'm having the same issue and already tried those. But I just tried System.gc(), and it does work. In my case, I'm closing a file inputstream and then moving the file. When there is an exception reading the file, the exception is propagated to the point where I'm done dealing with the file, and that's where I close it - and in the exception cases, I'm not able to to move the file. But if I close the inputstream before propagating the exception, I can. I had wondered if the difference was gc happening in between.
  • Andrea_86
    Andrea_86 about 9 years
    doesn't wotk for me. The file i can't delete is a ZIP file of a downloadedFromURL file. The nice thing is that the downloaded file will be deleted. Any idea?
  • Adam Burley
    Adam Burley about 9 years
    Worked for me. And @andreadi I never used FileChannel.map in my code. Seems that this bug got closed as unresolvable which makes me incredulous because the System.gc trick works every time.
  • notes-jj
    notes-jj almost 8 years
    Single gc() might not help System.gc(); result = file.delete(); if (!result){ Thread.sleep(100); System.gc(); result = file.delete(); }
  • Archie
    Archie almost 8 years
    This is only true on Windows. On any real O/S you can delete and rename open files.
  • Ulathar
    Ulathar over 6 years
    WoW thanks for posting your solution, this helped me a lot! I suffered a "file can not be deleted" Problem after migration from JDK7 to JDK9. Worked fine with JDK7, no longer worked with JDK9. Your top with calling System.gc() after the call of [...].close() solved this strange behaviour! Never would have figgured this out my self... I mean, Why Java, Why?
  • Markus Ressel
    Markus Ressel over 6 years
    @David 2018 with JDK 8 and I still have the same problem when trying to do file cleanup using a shutdown hook.
  • WesternGun
    WesternGun over 5 years
    I am with "try-with-resources" style with a FileWriter using a FileOutputStream created outside of try, and it is not auto-closed. I have to close it explicitly.