什么时候删除Java临时文件?


91

假设我使用以下方法在Java中创建了一个临时文件

File tmp = File.createTempFile(prefix, suffix);

如果我没有明确调用该delete()方法,什么时候删除该文件?

凭直觉,可能是JVM终止或更早(由Garbage Collector终止),或更(由某些操作系统清除进程终止)。



抱歉,我只检查了方法docs.oracle.com/javase/6/docs/api/java/io/…,但没有提供答案。仅在具有较长签名的方法中存在长描述。
Alphaaa

Answers:


94

该文件不会自动从JavaDoc中删除:

此方法仅提供临时文件功能的一部分。若要安排自动删除通过此方法创建的文件,请使用deleteOnExit()方法。

因此,您必须显式调用deleteOnExit()

请求在虚拟机终止时删除此抽象路径名表示的文件或目录。


2
如果使用deleteOnExit,它将在虚拟机终止时被删除。文件(或目录)以与注册时相反的顺序删除。调用此方法以删除已注册用于删除的文件或目录没有按照Java语言规范的定义,将仅尝试正常终止虚拟机进行删除。” 因此即使存在所有JVM,也不会删除它。
eis

谢谢,我只检查了方法docs.oracle.com/javase/6/docs/api/java/io/…,它没有提供答案。仅在具有较长签名的方法中提供详细说明
-Alphaaa

51

至于其他的答案注意到,与创建的临时文件File.createTempFile()不会被自动除非你明确要求它删除。

通用,可移植的方法来做到这一点是调用.deleteOnExit()File的对象,这将安排文件删除当JVM终止。但是,此方法的一个小缺点是,只有在VM正常终止时,它才起作用。在异常终止(即VM崩溃或VM进程的强制终止)时,该文件可能会保持未删除状态。

在Unixish系统(例如Linux)上,实际上可以通过在打开临时文件后立即删除临时文件来获得更可靠的解决方案。之所以可以这样做,是因为Unix文件系统允许删除一个文件(准确地说,是未链接的文件),同时仍由一个或多个进程保持打开状态。通常可以通过打开的文件句柄访问此类文件,并且只有在最后一个打开文件句柄的进程退出后,操作系统才会回收它们在磁盘上占据的空间。

因此,这是我知道确保程序退出后将正确删除临时文件的最可靠,最可移植的方式:

import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;

public class TempFileTest
{
    public static void main(String[] args)
    {
        try {
            // create a temp file
            File temp = File.createTempFile("tempfiletest", ".tmp"); 
            String path = temp.getAbsolutePath();
            System.err.println("Temp file created: " + path);

            // open a handle to it
            RandomAccessFile fh = new RandomAccessFile (temp, "rw");
            System.err.println("Temp file opened for random access.");

            // try to delete the file immediately
            boolean deleted = false;
            try {
                deleted = temp.delete();
            } catch (SecurityException e) {
                // ignore
            }

            // else delete the file when the program ends
            if (deleted) {
                System.err.println("Temp file deleted.");
            } else {
                temp.deleteOnExit();
                System.err.println("Temp file scheduled for deletion.");
            }

            try {
                // test writing data to the file
                String str = "A quick brown fox jumps over the lazy dog.";
                fh.writeUTF(str);
                System.err.println("Wrote: " + str);

                // test reading the data back from the file
                fh.seek(0);
                String out = fh.readUTF();
                System.err.println("Read: " + out);

            } finally {
                // close the file
                fh.close();
                System.err.println("Temp file closed.");
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在Unixish系统上,运行此命令应产生类似以下输出的内容:

Temp file created: /tmp/tempfiletest587200103465311579.tmp
Temp file opened for random access.
Temp file deleted.
Wrote: A quick brown fox jumps over the lazy dog.
Read: A quick brown fox jumps over the lazy dog.
Temp file closed.

而在Windows上,输出看起来略有不同:

Temp file created: C:\DOCUME~1\User\LOCALS~1\Temp\tempfiletest5547070005699628548.tmp
Temp file opened for random access.
Temp file scheduled for deletion.
Wrote: A quick brown fox jumps over the lazy dog.
Read: A quick brown fox jumps over the lazy dog.
Temp file closed.

但是,无论哪种情况,程序结束后,临时文件都不应保留在磁盘上。


附言 在Windows上测试此代码时,我观察到一个相当令人惊讶的事实:显然,仅使temp文件不关闭就足以防止其被删除。当然,这也意味着在使用临时文件时发生的任何崩溃都将导致该文件不删除,这正是我们在此要避免的事情。

AFAIK,避免这种情况的唯一方法是确保始终使用finally块关闭临时文件。当然,那么您也可以在同finally一块中删除该文件。我不确定使用什么.deleteOnExit()会真正使您受益。


好答案。值得注意的另一件事deleteOnExit()是,如果频繁调用它(例如,在使用许多新的临时文件的系统中),则可能会导致内存泄漏(因为它必须记住所有需要存储的路径)。删除)。
Eyal Roth

18

如果我没有明确调用该delete()方法,什么时候删除该文件?

至少Java不会这样做。如果要在JVM终止时删除该文件,则需要调用tmp.deleteOnExit()


5

来自:如何在Java中删除临时文件

临时文件用于存储次要的数据和临时数据, 在系统终止时应始终将其删除。最佳实践是使用File.deleteOnExit()来做到这一点。

例如,

File temp = File.createTempFile("abc", ".tmp"); 
temp.deleteOnExit();

上面的示例将创建一个名为“ abc.tmp”的临时文件,并在程序终止或退出时将其删除

如果要手动删除临时文件,仍然可以使用File.delete()。


为什么是最佳做法?
弗朗斯

3

临时文件用于存储次要的数据和临时数据,在系统终止时应始终将其删除。最佳实践是使用File.deleteOnExit()来做到这一点。

例如,

File temp = File.createTempFile("abc", ".tmp"); 
temp.deleteOnExit();

上面的示例将创建一个名为“ abc.tmp”的临时文件,并在程序终止或退出时将其删除。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.