ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

作为直觉,它可能是在 JVM 终止时,或者更早(通过垃圾收集器),或者更晚(通过某些操作系统清理进程)。

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

K
Kai

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

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

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

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


如果使用deleteOnExit,则会在“虚拟机终止时删除。文件(或目录)按照注册时的相反顺序删除。调用此方法删除已注册删除的文件或目录没有效果。只有在虚拟机正常终止时才会尝试删除,如 Java 语言规范所定义。所以即使在所有 JVM 存在时它也不会被删除。
谢谢,我只检查了方法docs.oracle.com/javase/6/docs/api/java/io/…,它没有提供答案。长描述仅存在于具有较长签名的方法中
I
Ilmari Karonen

正如其他答案所指出的,使用 File.createTempFile() 创建的临时文件将不会自动删除,除非您明确请求。

执行此操作的通用、可移植的方法是在 File 对象上调用 .deleteOnExit(),这将安排在 JVM 终止时删除文件。然而,这种方法的一个小缺点是它只有在 VM 正常终止时才有效。在异常终止(即虚拟机崩溃或强制终止虚拟机进程)时,文件可能保持未删除状态。

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

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

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 上测试此代码时,我观察到一个相当令人惊讶的事实:显然,仅保持临时文件不关闭就足以防止它被删除。当然,这也意味着在使用临时文件时发生的任何崩溃都会导致它未被删除,这正是我们在这里试图避免的。

AFAIK,避免这种情况的唯一方法是确保使用 finally 块关闭临时文件 always。当然,您也可以删除同一 finally 块中的文件。我不确定如果有的话,使用 .deleteOnExit() 会真正让你受益。


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

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

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


G
Grijesh Chauhan

来自:How to delete temporary file in Java

临时文件用于存储不太重要的临时数据,当您的系统终止时应始终将其删除。最佳做法是使用 File.deleteOnExit() 来执行此操作。

例如,

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

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

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


为什么这是最佳实践?
J
Juned Ahsan

临时文件用于存储不太重要的临时数据,当您的系统终止时应始终将其删除。最佳做法是使用 File.deleteOnExit() 来执行此操作。

例如,

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

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


J
Jasper Ketelaar

如果您愿意,您可以在终止进程之前手动删除文件,但是当进程终止时,文件也将被删除。


不,只有在您专门调用 deleteOnExit() 时才会在退出时将其删除