views:

9707

answers:

4

Is there a standard and reliable way of creating a temporary directory inside a Java application? There's an entry in Sun's issue database, which has a bit of code in the comments, but I wonder if there is a standard solution to be found in one of the usual libraries (Apache Commons etc.)

+30  A: 

This should do it

public static File createTempDirectory()
    throws IOException
{
    final File temp;

    temp = File.createTempFile("temp", Long.toString(System.nanoTime()));

    if(!(temp.delete()))
    {
        throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
    }

    if(!(temp.mkdir()))
    {
        throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
    }

    return (temp);
}

You could make better exceptions (subclass IOException) if you want.

TofuBeer
Nice touch of just reusing the guaranteed temporary name.
Thorbjørn Ravn Andersen
+1  A: 

Using File#createTempFile and delete to create a unique name for the directory seems ok. You should add a ShutdownHook to delete the directory (recursively) on JVM shutdown.

ordnungswidrig
A shutdown hook is cumbersome. Wouldn't File#deleteOnExit also work?
dhiller
You're right. #deleteOnExit shall work, too.
ordnungswidrig
#deleteOnExit didn't work for me - I believe it won't delete non-empty directories.
muriloq
+4  A: 

This is what I decided to do for my own code:

/**
 * Create a new temporary directory. Use something like
 * {@link #recursiveDelete(File)} to clean this directory up since it isn't
 * deleted automatically
 * @return  the new directory
 * @throws IOException if there is an error creating the temporary directory
 */
public static File createTempDir() throws IOException
{
    final File sysTempDir = new File(System.getProperty("java.io.tmpdir"));
    File newTempDir;
    final int maxAttempts = 9;
    int attemptCount = 0;
    do
    {
        attemptCount++;
        if(attemptCount > maxAttempts)
        {
            throw new IOException(
                    "The highly improbable has occurred! Failed to " +
                    "create a unique temporary directory after " +
                    maxAttempts + " attempts.");
        }
        String dirName = UUID.randomUUID().toString();
        newTempDir = new File(sysTempDir, dirName);
    } while(newTempDir.exists());

    if(newTempDir.mkdirs())
    {
        return newTempDir;
    }
    else
    {
        throw new IOException(
                "Failed to create temp dir named " +
                newTempDir.getAbsolutePath());
    }
}

/**
 * Recursively delete file or directory
 * @param fileOrDir
 *          the file or dir to delete
 * @return
 *          true iff all files are successfully deleted
 */
public static boolean recursiveDelete(File fileOrDir)
{
    if(fileOrDir.isDirectory())
    {
        // recursively delete contents
        for(File innerFile: fileOrDir.listFiles())
        {
            if(!FileUtilities.recursiveDelete(innerFile))
            {
                return false;
            }
        }
    }

    return fileOrDir.delete();
}
Keith
+6  A: 

Do not use deleteOnExit() even if you explicitly delete it later.

Google 'deleteonexit is evil' for more info, but the gist of the problem is:

1) deleteOnExit() only deletes for normal JVM shutdowns, not crashes or killing the JVM process.

2) deleteOnExit() only deletes on JVM shutdown - not good for long running server processes because:

3) The most evil of all - deleteOnExit() consumes memory for each temp file entry. If your process is running for months, or creates a lot of temp files in a short time, you consume memory and never release it until the JVM shuts down.

Developer Dude
We have a JVM where class and jar files get hidden files underneath created by the JVM, and this extra information takes quite a while to delete. When doing hot redeploys on web containers exploding WARs, the JVM can literaly take minutes to clean up after finishing but before exiting when having run for a few hours.
Thorbjørn Ravn Andersen