How to create a temporary directory/folder in Java?

Solution 1:

If you are using JDK 7 use the new Files.createTempDirectory class to create the temporary directory.

Path tempDirWithPrefix = Files.createTempDirectory(prefix);

Before JDK 7 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.

Solution 2:

The Google Guava library has a ton of helpful utilities. One of note here is the Files class. It has a bunch of useful methods including:

File myTempDir = Files.createTempDir();

This does exactly what you asked for in one line. If you read the documentation here you'll see that the proposed adaptation of File.createTempFile("install", "dir") typically introduces security vulnerabilities.

Solution 3:

If you need a temporary directory for testing and you are using jUnit, @Rule together with TemporaryFolder solves your problem:

@Rule
public TemporaryFolder folder = new TemporaryFolder();

From the documentation:

The TemporaryFolder Rule allows creation of files and folders that are guaranteed to be deleted when the test method finishes (whether it passes or fails)


Update:

If you are using JUnit Jupiter (version 5.1.1 or greater), you have the option to use JUnit Pioneer which is the JUnit 5 Extension Pack.

Copied from the project documentation:

For example, the following test registers the extension for a single test method, creates and writes a file to the temporary directory and checks its content.

@Test
@ExtendWith(TempDirectory.class)
void test(@TempDir Path tempDir) {
    Path file = tempDir.resolve("test.txt");
    writeFile(file);
    assertExpectedFileContent(file);
}

More info in the JavaDoc and the JavaDoc of TempDirectory

Gradle:

dependencies {
    testImplementation 'org.junit-pioneer:junit-pioneer:0.1.2'
}

Maven:

<dependency>
   <groupId>org.junit-pioneer</groupId>
   <artifactId>junit-pioneer</artifactId>
   <version>0.1.2</version>
   <scope>test</scope>
</dependency>

Update 2:

The @TempDir annotation was added to the JUnit Jupiter 5.4.0 release as an experimental feature. Example copied from the JUnit 5 User Guide:

@Test
void writeItemsToFile(@TempDir Path tempDir) throws IOException {
    Path file = tempDir.resolve("test.txt");

    new ListWriter(file).write("a", "b", "c");

    assertEquals(singletonList("a,b,c"), Files.readAllLines(file));
}

Solution 4:

Naively written code to solve this problem suffers from race conditions, including several of the answers here. Historically you could think carefully about race conditions and write it yourself, or you could use a third-party library like Google's Guava (as Spina's answer suggested.) Or you could write buggy code.

But as of JDK 7, there is good news! The Java standard library itself now provides a properly working (non-racy) solution to this problem. You want java.nio.file.Files#createTempDirectory(). From the documentation:

public static Path createTempDirectory(Path dir,
                       String prefix,
                       FileAttribute<?>... attrs)
                                throws IOException

Creates a new directory in the specified directory, using the given prefix to generate its name. The resulting Path is associated with the same FileSystem as the given directory.

The details as to how the name of the directory is constructed is implementation dependent and therefore not specified. Where possible the prefix is used to construct candidate names.

This effectively resolves the embarrassingly ancient bug report in the Sun bug tracker which asked for just such a function.

Solution 5:

This is the source code to the Guava library's Files.createTempDir(). It's nowhere as complex as you might think:

public static File createTempDir() {
  File baseDir = new File(System.getProperty("java.io.tmpdir"));
  String baseName = System.currentTimeMillis() + "-";

  for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
    File tempDir = new File(baseDir, baseName + counter);
    if (tempDir.mkdir()) {
      return tempDir;
    }
  }
  throw new IllegalStateException("Failed to create directory within "
      + TEMP_DIR_ATTEMPTS + " attempts (tried "
      + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')');
}

By default:

private static final int TEMP_DIR_ATTEMPTS = 10000;

See here