Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to File.deleteOnExit() in Java NIO?

Tags:

java

nio

Java IO has File.deleteOnExit(), which is a method that deletes the file it is called on during normal termination of the JVM. I've found this to be very useful for cleaning up temporary files, especially during unit tests.

However, I don't see a method by the same name in Java NIO's Files class. I am aware that I can do path.toFile().deleteOnExit(), but I'd like to know if there is an alternative using NIO.

Is there an alternative? If not, why is there not one?

like image 690
Thunderforge Avatar asked Feb 26 '15 20:02

Thunderforge


People also ask

What is Nio file in Java?

Java For Testers Java NIO package provide one more utility API named as Files which is basically used for manipulating files and directories using its static methods which mostly works on Path object.

How do I delete a file using Java NIO?

In Java, we can use the NIO Files. delete(Path) and Files. deleteIfExists(Path) to delete a file.

How do I delete an existing file in Java?

In Java, we can delete a file by using the File. delete() method of File class. The delete() method deletes the file or directory denoted by the abstract pathname. If the pathname is a directory, that directory must be empty to delete.


2 Answers

Short Answer

You can't delete arbitrary files in Java NIO, but you can use the StandardOpenOption.DELETE_ON_CLOSE when opening a new stream, which will delete the file as soon as the stream closes, either by calling .close() (including from a try-with-resources statement) or the JVM terminating. For instance:

Files.newOutputStream(Paths.get("Foo.tmp"), StandardOpenOption.DELETE_ON_CLOSE); 

Long Answer

After a great deal of digging around, I found that Java NIO does have a way to delete on exit, but it approaches it in a different way that Java I/O.

First off, the Javadoc for Files.createTempFile() describes three ways to delete files:

Where used as a work files [sic], the resulting file may be opened using the DELETE_ON_CLOSE option so that the file is deleted when the appropriate close method is invoked. Alternatively, a shutdown-hook, or the File.deleteOnExit() mechanism may be used to delete the file automatically.

The last choice, File.deleteOnExit() is of course a Java I/O method, which we are trying to avoid. A shutdown-hook is what is happening behind the scenes when you call the aforementioned method. But the DELETE_ON_CLOSE option is pure Java NIO.

Rather than deleting arbitrary files, Java NIO assumes that you are only interested in deleting files that you are actually opening. Therefore, methods that create a new stream such as Files.newOutputStream() can optionally take several OpenOptions, where you can input StandardOpenOption.DELETE_ON_CLOSE. What that does is delete the file as soon as the stream is closed (either by a call to .close() or the JVM exiting).

For instance:

Files.newOutputStream(Paths.get("Foo.tmp"), StandardOpenOption.DELETE_ON_CLOSE); 

...will delete the file associated with the stream when the stream is closed, either from an explicit call to .close(), the stream being closed as part of a try-with-resources statement, or the JVM terminating.

Update: On some operating systems such as Linux, StandardOpenOption.DELETE_ON_CLOSE deletes as soon as the OutputStream is created. If all you need is one OutputStream, that may still be okay. See DELETE_ON_CLOSE deletes files before close on Linux for more info.

So Java NIO adds new functionality over Java I/O in that you can delete a file when closing a stream. If that's a good enough alternative to deleting during JVM exit, you can do it in pure Java NIO. If not, you'll have to rely on Java I/O's File.deleteOnExit() or a shutdown-hook to delete the file.

like image 112
Thunderforge Avatar answered Oct 02 '22 15:10

Thunderforge


Behind the scenes, File.deleteOnExit() will just create a shutdown hook via Runtime.addShutdownHook().

Then, you can do the same thing with NIO:

Runtime.getRuntime().addShutdownHook(new Thread() {   public void run() {     Path path = ...;      Files.delete(path);   } }); 
like image 21
JoaaoVerona Avatar answered Oct 02 '22 16:10

JoaaoVerona