views:

8008

answers:

11

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?

+3  A: 

There is no reason you should not be able to delete this file. I would look to see who has a hold on this file. In unix/linux, you can use the lsof utility to check which process has a lock on the file. In windows, you can use process explorer.

for lsof, it's as simple as saying:

lsof /path/and/name/of/the/file

for process explorer you can use the find menu and enter the file name to show you the handle which will point you to the process locking the file.

here is some code that does what I think you need to do:

                    FileOutputStream to;

                try {
                        String file = "/tmp/will_delete.txt";
      to = new FileOutputStream(file );
                        to.write(new String("blah blah").getBytes());
                        to.flush();
                        to.close();
                        File f = new File(file);
                        System.out.print(f.delete());
                } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }

It works fine on OS X. I haven't tested it on windows but I suspect it should work on Windows too. I will also admit seeing some unexpected behavior on Windows w.r.t. file handling.

neesh
For windows, you can download the free Process Explorer from MS: http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
kd304
A: 

May you show us also your code to delete the file ? Put some trace output System.err.println(file.getName()) in your code and check if you point to the same file.

PeterMmm
+2  A: 

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.

Jenny Smith
I would argue it's a bug then:http://java.sun.com/javase/6/docs/api/java/io/BufferedReader.html#close()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.
Ravi Wallau
+2  A: 

You're only closing the file if you get to the end of the try block without throwing an exception. You should close it in a finally block instead... it's possible that's the problem, if any exceptions were thrown.

Jon Skeet
A: 

Who owns the file? Are you creating it under one user context and trying to delete it in another? Your second process may not be allowed to delete the file.

Alan Moore
No, it's the same user. I create it, read it, write something else in it, later delete it. And no exceptions were caught, so I don't know why it didn't work with BufferedReader.
Jenny Smith
A: 

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.

Ravi Wallau
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.
Jenny Smith
A: 

Hopefully this will help. I came across similar problem where i couldn't delete my file after my java code made a copy of the content to the other folder. After extensive googling, i explicitly declared every single file operation related variables and called the close() method of each file operation object, and set them to NULL. Then, there is a function called System.gc(), which will clear up the file i/o mapping (i'm not sure, i just tell what is given on the web sites).

Here is my example code:

public void start() {
    File f = new File(this.archivePath + "\\" + this.currentFile.getName());
    this.Copy(this.currentFile, f);

    if(!this.currentFile.canWrite()){
        System.out.println("Write protected file " +
           this.currentFile.getAbsolutePath());

        return;
    }


    boolean ok = this.currentFile.delete();
    if(ok == false){
        System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
        return;
    }
}

private void Copy(File source, File dest) throws IOException {
    FileInputStream fin;
    FileOutputStream fout;
    FileChannel cin = null, cout = null;
    try {
        fin = new FileInputStream(source);
        cin = fin.getChannel();
        fout = new FileOutputStream(dest);
        cout = fout.getChannel();

        long size = cin.size();
        MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);

        cout.write(buf);
        buf.clear();
        buf = null;

        cin.close();
        cin = null;

        fin.close();
        fin = null;

        cout.close();
        cout = null;

        fout.close();
        fout = null;

        System.gc();

    } catch (Exception e){
        this.message = e.getMessage();
        e.printStackTrace();
    }
}
poh
+1  A: 

Yes, The above mentioned trick worked for me too. :) System.gc(); is what is required after all the input/ouput Stream and buffer close()/flush() to delete a file. file.delete() is very weired I must say.... Ranjit

Ranjit
That's weird. Requiring garbage collector likely means that filehandler was not closed after write but closed by finalizer. I have meet several problems like this on Windows 7 and can not track the cause of it.
Petr Gladkikh
A: 

Whit System.gc(); is working, i had this sentence in the Finally after donwolad a file by Zip.

Bye

Fernanado Parra
A: 

Yep, System.gc() solves the problem. Thanks a lot!! :):)

Divya
A: 

For me it does not work. I listed the directory like file.listFiles(). And afterward tried to remove some of the listed files. The files are in the Temp directory. Does not work. SO, I would say any System.gc() is not an execuse. That's just stuped. Along with another stuff written very very very bad in java for Windows. People in Oracle doesn't care I think, because the problem is not the first year here.

Ilya