Please consider the following example Java class (pom.xml below):
package test.filedelete;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import org.apache.commons.io.IOUtils;
public class Main
{
public static void main(String[] args) throws IOException
{
byte[] bytes = "testtesttesttesttesttesttesttesttesttest".getBytes();
InputStream is = new ByteArrayInputStream(bytes);
Path tempFileToBeDeleted = Files.createTempFile("test", "");
OutputStream os = Files.newOutputStream(tempFileToBeDeleted);
IOUtils.copy(is, os);
deleteAndCheck(tempFileToBeDeleted);
// breakpoint 1
System.out.println("\nClosing stream\n");
os.close();
deleteAndCheck(tempFileToBeDeleted);
}
private static void deleteAndCheck(Path file) throws IOException
{
System.out.println("Deleting file: " + file);
try
{
Files.delete(file);
}
catch (NoSuchFileException e)
{
System.out.println("No such file");
}
System.out.println("File really deleted: " + !Files.exists(file));
System.out.println("Recreating deleted file ...");
try
{
Files.createFile(file);
System.out.println("Recreation successful");
}
catch (IOException e)
{
System.out.println("Recreation not possible, exception: " + e.getClass().getName());
}
}
}
I write to a FileOutputStream and try to delete the file afterwards without closing the Stream first. This was my original problem, and of course wrong, but it leads to some strange observations.
When you run the main Method on Windows 7 it produces the following output:
Deleting file: C:\Users\MSCHAE~1\AppData\Local\Temp\test6100073603559201768
File really deleted: true
Recreating deleted file ...
Recreation not possible, exception: java.nio.file.AccessDeniedException
Closing stream
Deleting file: C:\Users\MSCHAE~1\AppData\Local\Temp\test6100073603559201768
No such file
File really deleted: true
Recreating deleted file ...
Recreation successful
- Why does the first call to Files.delete() not throw an exception?
- Why does the following call to Files.exist() return false?
- Why is it not possible to create the file anew?
Regarding the last question I noticed that the file is still visible in the Explorer when you stop at breakpoint 1. When you terminate the JVM then, the file will be deleted anyway. After closing the stream deleteAndCheck() works as expected.
It seems to me that the deletion is not propagated to the OS before closing the stream and the Files API does not reflect this properly.
Can someone explain exactly what's happening here?
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>filedelete</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</project>
Update for clarification
The file disappears in the Windows explorer, if the stream is closed AND Files.delete() is called - the last operation triggers -, or if Files.delete() has been called without closing the stream and the JVM is terminated.
Files.copy()
to copy the contents of anInputStream
into aPath
; no need for IOUtils – PomeraniaFiles.delete(file);
and then stepping past it. Does the file actually disappear from the explorer window at that moment? I'm suspicious that somehow the delete succeeds, but windows is keeping the file because there is another reference open to it. This may be something low level in the way windows works. I would not expect the same on a Posix (eg: Linux) system. – Blackmun