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

Alp*_*aaa 79 java garbage-collection temporary-files

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

File tmp = File.createTempFile(prefix, suffix);
Run Code Online (Sandbox Code Playgroud)

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

作为一种直觉,它可能是JVM终止时,或更早(由垃圾收集器)或更(通过某些操作系统清扫过程).

Kai*_*Kai 81

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

此方法仅提供临时文件工具的一部分.要安排自动删除此方法创建的文件,请使用deleteOnExit()方法.

所以你必须显式调用deleteOnExit():

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

  • 如果使用deleteOnExit,它将被删除"当虚拟机终止时.文件(或目录)按照它们注册的相反顺序删除.调用此方法删除已注册删除的文件或目录没有根据Java语言规范的定义,只会尝试删除虚拟机的正常终止." 所以即使在所有JVM都存在的情况下它也不会被删除. (2认同)

Ilm*_*nen 50

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

通用,可移植的方法来做到这一点是调用.deleteOnExit()File的对象,这将安排文件删除当JVM终止.然而,这种方法的一个小缺点是它只能在VM正常终止时起作用; 在异常终止(即VM崩溃或VM进程强制终止)时,该文件可能仍未删除.

在Unixish系统(例如Linux)上,通过在打开临时文件后立即删除临时文件,实际上可以获得更可靠的解决方案.这是有效的,因为Unix文件系统允许在一个或多个进程仍然保持打开的情况下删除文件(取消链接,准确无误).这些文件可以通过打开的文件句柄正常访问,并且它们在磁盘上占用的空间只有在持有文件的打开句柄的最后一个进程退出后才由OS回收.

所以这是我所知道的最可靠和最便携的方法,以确保在程序退出后正确删除临时文件:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在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.
Run Code Online (Sandbox Code Playgroud)

而在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.
Run Code Online (Sandbox Code Playgroud)

但是,在任何一种情况下,程序结束后临时文件都不应保留在磁盘上.


PS.在Windows上测试这段代码时,我发现了一个相当令人惊讶的事实:显然,仅仅保留临时文件未被封闭就足以防止它被删除.当然,这也意味着临时文件正在使用时发生的任何崩溃都会导致它被取消删除,这正是我们在这里要避免的.

AFAIK,避免这种情况的唯一方法是确保使用块始终关闭临时文件finally.当然,你也可以删除同一个finally块中的文件.我不确定使用什么,如果有的话,.deleteOnExit()实际上会让你获益.

  • 很好的答案。关于“deleteOnExit()”另一个需要注意的重要事情是,如果频繁调用它(例如,在使用大量新临时文件的系统中),它可能会导致内存泄漏(因为它有记住所有需要删除的路径)。 (2认同)

Ian*_*rts 18

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

它不会,至少不是Java.如果您希望在JVM终止时删除该文件,则需要调用tmp.deleteOnExit().


Gri*_*han 5

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

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

例如,

File temp = File.createTempFile("abc", ".tmp"); 
temp.deleteOnExit();
Run Code Online (Sandbox Code Playgroud)

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

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