Java Create Temp File or Directory (with Cleanup Examples)

Create a temp file or folder in Java with Files.createTempFile() and Files.createTempDirectory(). See how the older File.createTempFile() differs, and delete temp files safely with finally, DELETE_ON_CLOSE, deleteOnExit() or JUnit @TempDir.

To create a temp file in Java, we call Files.createTempFile(prefix, suffix). The method creates a new, empty file with a random name in the system temp folder and returns its Path. A temporary file (temp file) holds data that a program needs only for a short time, so we delete it when the work is done.

We use temp files for uploads and batch results, for example a CSV report that the app builds and sends by email before it deletes the file.

The following example creates a temp file with Files.createTempFile(), the older File.createTempFile() and the Files.createTempDirectory() method, with the result of each line as a comment.

Path report = Files.createTempFile("report-", ".csv");     // /tmp/report-9963592177676969650.csv
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(report);   // [OWNER_READ, OWNER_WRITE] (rw-------)

File legacy = File.createTempFile("report-", ".csv");      // /tmp/report-223026811981626616.csv (rw-r--r--)
Path workDir = Files.createTempDirectory("reports-");      // /tmp/reports-11541217976960533970 (rwx------)
Path daily = Files.createTempFile(workDir, "daily-", ".csv");
                                                            // /tmp/reports-1154.../daily-5092546280111486842.csv
String tmpDir = System.getProperty("java.io.tmpdir");       // /tmp (Linux)

Files.writeString(report, "name,age\nLokesh,37\n");
List<String> lines = Files.readAllLines(report);            // [name,age, Lokesh,37]
boolean deleted = Files.deleteIfExists(report);             // true

Notice that the file from Files.createTempFile() gets rw——-, whereas the file from the older File.createTempFile() gets rw-r–r–.

Next, we see where temp files go and compare Files.createTempFile() with File.createTempFile(), which give the new file different permissions (that is, different rules for who may read or write it). After that, we compare the ways to delete temp files, including @TempDir in JUnit tests, and see how to keep temp files safe in a shared /tmp folder.

For temp files or folders in unit tests, we should use @TempDir (JUnit 5 and 6) or TemporaryFolder (JUnit 4). JUnit creates the folder before the test and deletes it with all its files after the test, whether the test passes or fails. Section 6 shows an example.

1. Default Location of Temp Files or Directories

When we do not pass a folder, Java puts the temp file in the default temp folder, whose path comes from the system property java.io.tmpdir (a named setting that the JVM reads at startup). The default value depends on the OS.

OSDefault java.io.tmpdir
Linux/tmp
macOSa folder for each user under /var/folders/…, read from the TMPDIR variable
WindowsC:\Users\<user>\AppData\Local\Temp\, read from the TMP variable

To use another folder, we pass a command-line option when we start the JVM.

java -Djava.io.tmpdir=/data/tmp -jar app.jar

For example, when we started the program with -Djava.io.tmpdir=/tmp/tmpfile-build/mytmp, Files.createTempFile(“report-“, “.csv”) returned /tmp/tmpfile-build/mytmp/report-13380639746103217900.csv. Calling System.setProperty(“java.io.tmpdir”, …) in code has no effect, because the JDK reads the value only once, at startup. In our test on JDK 25, we set the property in the first line of main(), and both temp file methods still used /tmp.

The target folder must also exist. If the folder is missing, the JVM prints a warning and the call fails.

WARNING: java.io.tmpdir directory does not exist
Exception in thread "main" java.nio.file.NoSuchFileException: /tmp/tmpfile-build/nope/report-1836379163320172177.csv

2. Create Temp Files

Java has two methods that create a temp file. Both build the file name from the prefix, a random number and the suffix, and both create the file only if no file with that name exists yet, so two threads or two programs never get the same file. The main difference is the file permissions on Linux and macOS.

Files.createTempFile() (NIO, Java 7+)File.createTempFile() (older API)
ReturnsPathFile
Permissions on POSIX systemsrw——- (only the owner)rw-r–r– with the usual umask 022 (everyone can read)
Custom permissionsyes, with a FileAttribute argumentno
Shortest allowed prefixno limit, null or “” allowed3 characters, else IllegalArgumentException
null suffix.tmp.tmp
Folder does not existNoSuchFileExceptionIOException: No such file or directory
Recommendedyesonly for old code that needs a File

Two terms in the table need a short explanation. POSIX is the standard that Linux and macOS follow for file permissions, and the umask is a per-process setting that removes some permission bits from every new file. The value 022 removes write access for the group and for all other users. When we run ls -l on the two files from the quick-reference snippet, we see their permissions.

-rw------- 1 root root 0 Oct  3 22:55 /tmp/report-10890120786580706513.csv
-rw-r--r-- 1 root root 0 Oct  3 22:55 /tmp/report-1309365777000057237.csv

Only the owner can read or write the first file, which comes from Files.createTempFile(), whereas every user on the machine can read the second file from File.createTempFile(). On Windows, both files get the default access rights of the temp folder.

2.1. Using Files.createTempFile() [Java NIO]

The java.nio.file.Files.createTempFile()) method has two versions with different parameters, which makes it an overloaded method.

Path createTempFile(String prefix, String suffix, FileAttribute<?>... attrs)
Path createTempFile(Path dir, String prefix, String suffix, FileAttribute<?>... attrs)
  • The parameter dir is the folder for the new file. The first version has no dir and uses the default temp folder from section 1.
  • The parameter prefix is the start of the file name. It may be null or empty, but it must not contain a path separator such as /.
  • The parameter suffix is the end of the file name, most often the extension. When the suffix is null, Java uses “.tmp”.
  • The parameter attrs holds optional file attributes, such as POSIX permissions. Java sets them in the same step that creates the file, so no other program sees the file without them.

Each line of the next snippet shows what one combination of prefix and suffix gives.

Path withSuffix = Files.createTempFile("report-", ".csv");         // report-9963592177676969650.csv
Path noSuffix = Files.createTempFile("report-", null);             // report-4225592920992266332.tmp
Path noName = Files.createTempFile(null, null);                    // 12904529035942842415.tmp
Path badPrefix = Files.createTempFile("reports/2026-", ".csv");    // IllegalArgumentException: Invalid prefix or suffix
Path noDir = Files.createTempFile(Path.of("/no/such/dir"), "r-", ".txt");
                                                                   // NoSuchFileException: /no/such/dir/r-11406574224907898522.txt

To create the file in our own folder, we pass that folder as the first argument. The folder must exist, and one way to get a private folder is Files.createTempDirectory() from section 3.

Path workDir = Files.createTempDirectory("reports-");
Path daily = Files.createTempFile(workDir, "daily-", ".csv");
// /tmp/reports-11541217976960533970/daily-5092546280111486842.csv

The FileAttribute argument sets the permissions when Java creates the file, but the umask still applies, so if we ask for rw-rw-rw- and the umask is 022, the file gets rw-r–r–. Windows does not support POSIX attributes, so on Windows the call throws UnsupportedOperationException.

FileAttribute<Set<PosixFilePermission>> attrs =
    PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-rw-rw-"));

Path shared = Files.createTempFile(workDir, "shared-", ".csv", attrs);
String perms = PosixFilePermissions.toString(Files.getPosixFilePermissions(shared));   // rw-r--r--

To write data to the temporary file, we use the normal Files methods shown in section 4, and section 5 compares the ways to delete the file after the work.

2.2. Using File.createTempFile() [Legacy]

The java.io.File.createTempFile()) method works like Files.createTempFile(), because it creates a new, empty file in the given folder and builds the file name from the prefix and the suffix. The difference is the return type, because this method belongs to the older java.io API and returns a File, not a Path.

File createTempFile(String prefix, String suffix) throws IOException
File createTempFile(String prefix, String suffix, File directory) throws IOException

The older method needs a prefix of at least three characters, and a shorter prefix throws IllegalArgumentException.

File tempFile = File.createTempFile("report-", ".csv");
String path = tempFile.getAbsolutePath();      // /tmp/report-223026811981626616.csv

File tooShort = File.createTempFile("ab", ".csv");   // IllegalArgumentException: Prefix string "ab" too short: length must be at least 3

To delete the temp file when the JVM ends normally, we call deleteOnExit().

File tempFile = File.createTempFile("report-", ".csv");
tempFile.deleteOnExit();     // deletes the file when the JVM exits normally

When old code needs a File object, we create the file with Files.createTempFile() and convert the result with toFile(), so the file keeps the safer owner-only permissions.

File tempFile = Files.createTempFile("report-", ".csv").toFile();

3. Creating Temp Directory

A temp folder helps when a task writes several files, for example, a ZIP export that holds one CSV file per day. Files.createTempDirectory() has the same two versions as Files.createTempFile(), except that there is no suffix.

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

In most cases, we pass only a prefix for the folder name. On Linux and macOS, the new folder gets the permissions rwx——, so only the owner can open it.

Path tempDir = Files.createTempDirectory("reports-");                      // /tmp/reports-11541217976960533970
Path inData = Files.createTempDirectory(Path.of("/data/tmp"), "reports-"); // /data/tmp/reports-...
drwx------ 2 root root 4096 Oct  3 22:55 /tmp/reports-3828946619802742854

Java does not delete a temp directory on its own, and deleteOnExit() deletes only an empty directory. In our test, a folder with one file and deleteOnExit() was still in /tmp after the JVM ended, whereas an empty folder was gone. To remove a folder with its content, we use Files.walk(), which lists the folder and everything inside it. We sort that list in reverse order, so Java deletes the files first and the folder that holds them last.

try (Stream<Path> paths = Files.walk(tempDir)) {
  paths.sorted(Comparator.reverseOrder())
      .forEach(path -> {
        try {
          Files.delete(path);
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      });
}

The try-with-resources block closes the stream, which Files.walk() needs to release the open folder handles. We run this code in a finally block, so it also runs after an exception.

Another option is a shutdown hook (a thread that the JVM runs when the program exits normally), which we register with Runtime.getRuntime().addShutdownHook(). A shutdown hook does not run when someone stops the process with kill -9 or when the machine loses power, so a finally block is the safer place to delete a directory recursively.

4. Writing and Reading a Temp File

A temp file is a normal file, so all Files methods work on it. For small content, Files.writeString() and Files.readAllLines() fit well, and for content that we write line by line, a BufferedWriter fits better.

Path data = Files.createTempFile("report-", ".csv");
try {
  Files.writeString(data, "name,age\nLokesh,37\nAlex,29\n");
  List<String> lines = Files.readAllLines(data);     // [name,age, Lokesh,37, Alex,29]
  long size = Files.size(data);                      // 27
} finally {
  Files.deleteIfExists(data);
}
boolean exists = Files.exists(data);                 // false
Path report = Files.createTempFile("report-", ".csv");
try (BufferedWriter writer = Files.newBufferedWriter(report)) {
  writer.write("name,age");
  writer.newLine();
  writer.write("Lokesh,37");
}
String content = Files.readString(report);           // "name,age\nLokesh,37"

Both methods use UTF-8 by default. For appending, large files and other encodings, we write to a file or read a file to a String with the other Files methods.

5. Deleting Temp Files

Java never deletes a temp file by itself, so a file in /tmp stays until the next reboot or until a cleanup job of the OS removes it. A server that runs for months can fill its disk with forgotten temp files. Java offers three ways to delete a temp file, and each one deletes the file at a different moment.

OptionWhen the file is deletedUse it when
Files.deleteIfExists() in finallyright after the work, also after an exceptionthe default for application code
StandardOpenOption.DELETE_ON_CLOSEwhen the stream or channel is closedonly one stream or channel uses the file
File.deleteOnExit()when the JVM exits normallyshort command-line programs
@TempDir (JUnit)after each testtests
Timeline of a temp file from creation to JVM exit. Files.deleteIfExists in a finally block deletes the file right after the work. With DELETE_ON_CLOSE on Linux, the file name disappears when the channel opens, and the data is freed when the channel closes. deleteOnExit deletes the file only when the JVM exits normally. The file stays after kill -9 or a crash.
deleteIfExists() in finally deletes the file first, even after an exception. deleteOnExit() waits until the JVM exits.

5.1. Using Files.deleteIfExists() in a finally Block

For application code, we delete the temp file in a finally block. The finally block runs after the work, even when the work throws an exception. If the file is already gone, Files.deleteIfExists() returns false and does not throw.

Path upload = Files.createTempFile("upload-", ".csv");
try {
  // write and process the file
} finally {
  Files.deleteIfExists(upload);
}

Code that works with File objects can also delete a temporary file with File.delete() in the same finally block.

5.2. Using StandardOpenOption.DELETE_ON_CLOSE

When we open the file with the DELETE_ON_CLOSE option, Java deletes the file when the stream or channel closes. In the example, we open a SeekableByteChannel (an object that reads and writes bytes at any position in a file) with the READ and WRITE options, so we can write the data and read it back before the close.

Path scratch = Files.createTempFile("scratch-", ".bin");
try (SeekableByteChannel channel = Files.newByteChannel(scratch,
    StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE)) {

  channel.write(ByteBuffer.wrap("Lokesh,37".getBytes(StandardCharsets.UTF_8)));
  channel.position(0);
  ByteBuffer buffer = ByteBuffer.allocate(64);
  channel.read(buffer);                    // "Lokesh,37"
  boolean visible = Files.exists(scratch); // false (on Linux)
}
boolean exists = Files.exists(scratch);    // false

The second-to-last line surprises many developers, because Files.exists() returns false while the channel is still open. On Linux, the JDK removes the file name right after opening the file, and the open channel keeps working with the data. The OS frees the disk space when the channel closes, whereas on Windows the file stays visible until the close.

On both systems, no other code can open the file by its name later, so DELETE_ON_CLOSE fits only when one stream or channel does all the work. For example, opening the file with Files.newOutputStream(path, DELETE_ON_CLOSE) and then reading it with Files.readAllLines(path) does not work.

5.3. Using File.deleteOnExit()

The method deleteOnExit() marks the file for deletion, and the JVM deletes it when the program exits normally. To use the method with a Path, we first convert the Path to a File with toFile().

Path tempFile = Files.createTempFile("report-", ".csv");
tempFile.toFile().deleteOnExit();

The method deleteOnExit() has three limits.

  • The JVM keeps every marked path in memory until the program exits, and we cannot cancel a mark, so a server that creates thousands of temp files keeps growing that list.
  • The file stays on disk until the JVM exits. For a server, that can be weeks.
  • Nothing is deleted after kill -9, a crash or Runtime.halt(), and a folder is deleted only when it is empty.

6. Temp Files in JUnit Tests With @TempDir

In tests, JUnit can manage the temp folder for us. When we put @TempDir on a field or a test method parameter, JUnit creates a new folder and passes it to the test. After the test, JUnit deletes the folder with all its content.

@TempDir
Path tempDir;

@Test
void writesReportIntoTempDir() throws IOException {
  Path report = tempDir.resolve("report.csv");
  Files.writeString(report, "name,age\nLokesh,37\n");

  assertEquals(List.of("name,age", "Lokesh,37"), Files.readAllLines(report));
  // tempDir = /tmp/junit-3011162256665048580, deleted after the test
}

The test passed, and after the run the folder /tmp/junit-3011162256665048580 was gone. When we want to look at the files of a failed test, we use CleanupMode.ON_SUCCESS, so JUnit deletes the folder only when the test passes and keeps it after a failure.

@Test
void keepsFilesOnFailure(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path debugDir) throws IOException {
  Path report = Files.createFile(debugDir.resolve("report.csv"));
  assertTrue(Files.exists(report));
}

A static @TempDir field gives one JUnit temp directory to all tests of a class.

7. Security of Temp Files in a Shared /tmp

On Linux, all users and programs on the machine share the /tmp folder, so other users may read or change a temp file that holds an upload, a login token or customer data. Unsafe temp files are a known weakness, listed as CWE-377, so we follow four rules.

  • We never build a temp file name ourselves, for example new File(“/tmp/report-” + userId + “.csv”). Another user can guess a name built that way and create the file first, or a symbolic link (a shortcut to another file) with that name. Files.createTempFile() picks a random name and fails if the file already exists, so our program never writes into a file that someone else prepared.
  • We use Files.createTempFile() and Files.createTempDirectory(), because only the owner can read their files, whereas with the usual umask every user can read files from File.createTempFile().
  • For sensitive data, we create one private folder with Files.createTempDirectory() and put all files of the task inside it.
  • We delete the files as soon as the work is done (section 5).

8. Temp File FAQs

8.1. Is Files.createTempFile() Thread-Safe?

Yes. Each call creates a new file with a random name, and if a file with that name already exists, the method tries another name. So two threads that call Files.createTempFile(“report-“, “.csv”) at the same time always get two different files.

8.2. How Do I Create a Temp File With a Fixed Name?

Temp file methods always add a random part to the name, so for a fixed name we first create a private temp folder and then create a normal file inside it with Files.createFile().

Path dir = Files.createTempDirectory("export-");
Path file = Files.createFile(dir.resolve("report.csv"));   // /tmp/export-.../report.csv

8.3. Why Is My Temp File Not Deleted After the Program Ends?

Java deletes a temp file only when our code asks for it, so a leftover file has one of four common causes.

  • The code never calls deleteIfExists().
  • An exception happens before the delete call, and there is no finally block.
  • The code calls deleteOnExit() on a folder that is not empty.
  • Someone stops the JVM with kill -9, so deleteOnExit() does not run.

8.4. When Does the OS Delete Files in /tmp?

The answer depends on how the OS is set up. Many Linux systems clear /tmp at every boot, while others remove old files with a tool called systemd-tmpfiles. Windows does not clean its temp folder unless the user runs a cleanup tool, so a Java program should not depend on either.

9. Conclusion

In Java, Files.createTempFile() and Files.createTempDirectory() are the best way to create a temporary file or folder, because both pick a random name that never matches an existing file, and on Linux and macOS only the owner can read the new file. File.createTempFile() still works, but every user can read its files.

We delete temp files in a finally block with Files.deleteIfExists(), and use DELETE_ON_CLOSE only when one channel does all the work. The method deleteOnExit() fits short programs, and in tests, @TempDir creates and removes the folder for us.

10. References

Happy Learning !!

Source Code on Github

Leave a Comment

  1. Hi Pankaj,

    The only problem which i face while using this api are the random number which get added while creating the file.

    [File Name] **** Random Number **** [File Extension]

    Is there any way i can handle the name of the temporary file in my way, as certain use case need the file name in

    advance.

    Regards,
    Himansu

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.