Wann werden temporäre Java-Dateien gelöscht?

88

Angenommen, ich erstelle mit der Methode eine temporäre Datei in Java

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

Wenn ich die delete()Methode nicht explizit aufrufe , wann wird die Datei gelöscht?

Als Intuition kann es sein, dass die JVM beendet wird oder früher (durch den Garbage Collector) oder später (durch einen Betriebssystem-Sweeping-Prozess).

Alphaaa
quelle
2
deleteOnExit ()
devnull
Ich entschuldige mich, ich habe nur die Methode docs.oracle.com/javase/6/docs/api/java/io/… überprüft , die keine Antwort liefert. Die lange Beschreibung ist nur in der Methode mit der längeren Signatur vorhanden.
Alphaaa

Antworten:

91

Die Datei wird nicht automatisch aus dem JavaDoc gelöscht :

Diese Methode bietet nur einen Teil einer temporären Dateifunktion. Verwenden Sie die Methode deleteOnExit (), damit eine mit dieser Methode erstellte Datei automatisch gelöscht wird.

Sie müssen also explizit deleteOnExit () aufrufen :

Fordert an, dass die mit diesem abstrakten Pfadnamen angegebene Datei oder das Verzeichnis gelöscht wird, wenn die virtuelle Maschine beendet wird.

Kai
quelle
2
und wenn deleteOnExit verwendet wird, wird es gelöscht, "wenn die virtuelle Maschine beendet wird. Dateien (oder Verzeichnisse) werden in der umgekehrten Reihenfolge gelöscht, in der sie registriert sind. Wenn Sie diese Methode zum Löschen einer Datei oder eines Verzeichnisses aufrufen, die / das bereits zum Löschen registriert ist, haben Sie keine." Der Löschvorgang wird nur für die normale Beendigung der virtuellen Maschine gemäß der Java-Sprachspezifikation versucht. " Daher wird es nicht gelöscht, selbst wenn alle JVMs vorhanden sind.
Eis
danke, ich habe nur die Methode docs.oracle.com/javase/6/docs/api/java/io/… überprüft , die keine Antwort liefert. Die lange Beschreibung ist nur in der Methode mit der längeren Signatur vorhanden
Alphaaa
51

Wie in den anderen Antworten vermerkt, werden temporäre Dateien, mit denen erstellt wurde File.createTempFile(), nicht automatisch gelöscht, es sei denn, Sie fordern dies ausdrücklich an.

Die generische, tragbare Methode hierfür besteht darin, .deleteOnExit()das FileObjekt aufzurufen , das das Löschen der Datei beim Beenden der JVM plant. Ein kleiner Nachteil dieser Methode ist jedoch, dass sie nur funktioniert, wenn die VM normal beendet wird. Bei einer abnormalen Beendigung (dh einem VM-Absturz oder einer erzwungenen Beendigung des VM-Prozesses) bleibt die Datei möglicherweise nicht gelöscht.

Auf Unixish-Systemen (wie Linux) ist es tatsächlich möglich, eine etwas zuverlässigere Lösung zu erhalten, indem die temporäre Datei unmittelbar nach dem Öffnen gelöscht wird . Dies funktioniert , weil Unix - Dateisysteme erlauben eine Datei (gelöscht werden nicht verknüpft , um genau zu sein) , während es noch durch einen oder mehrere Prozesse offen gehalten wird . Auf solche Dateien kann normalerweise über das geöffnete Dateihandle zugegriffen werden, und der Speicherplatz, den sie auf der Festplatte belegen, wird vom Betriebssystem erst nach dem letzten Vorgang zurückgefordert, bei dem ein offenes Handle für die Datei beendet wird.

Hier ist die zuverlässigste und portabelste Methode, die ich kenne, um sicherzustellen, dass eine temporäre Datei nach dem Beenden des Programms ordnungsgemäß gelöscht wird:

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();
        }
    }
}

Wenn Sie dies auf einem Unixish-System ausführen, sollte dies ungefähr die folgende Ausgabe erzeugen:

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.

Unter Windows sieht die Ausgabe etwas anders aus:

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.

In beiden Fällen sollte die temporäre Datei jedoch nach Beendigung des Programms nicht auf der Festplatte verbleiben.


Ps. Beim Testen dieses Codes unter Windows habe ich eine ziemlich überraschende Tatsache festgestellt: Anscheinend reicht es aus, die temporäre Datei nicht geschlossen zu lassen, um zu verhindern, dass sie gelöscht wird . Dies bedeutet natürlich auch, dass jeder Absturz, der während der Verwendung der temporären Datei auftritt, dazu führt, dass sie nicht gelöscht wird. Genau das versuchen wir hier zu vermeiden .

AFAIK, die einzige Möglichkeit, dies zu vermeiden, besteht darin, sicherzustellen, dass die temporäre Datei immer mit einem finallyBlock geschlossen wird . Dann können Sie natürlich auch die Datei im selben finallyBlock löschen . Ich bin mir nicht sicher, was Sie, wenn überhaupt, .deleteOnExit()tatsächlich dazu bringen würde.

Ilmari Karonen
quelle
Gute Antwort. Ein weiterer wichtiger Punkt deleteOnExit()ist, dass ein häufiger Aufruf (z. B. in einem System, das viele neue temporäre Dateien verwendet) wahrscheinlich einen Speicherverlust verursacht (da alle erforderlichen Pfade gespeichert werden müssen) gelöscht).
Eyal Roth
18

Wenn ich die delete()Methode nicht explizit aufrufe , wann wird die Datei gelöscht?

Zumindest nicht von Java. Wenn Sie möchten, dass die Datei beim Beenden der JVM gelöscht wird, müssen Sie aufrufen tmp.deleteOnExit().

Ian Roberts
quelle
5

von: So löschen Sie temporäre Dateien in Java

Temporäre Datei wird verwendet, um die weniger wichtigen und temporären Daten zu speichern, die immer gelöscht werden sollten, wenn Ihr System beendet wird . Am besten verwenden Sie dazu File.deleteOnExit ().

Beispielsweise,

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

Im obigen Beispiel wird eine temporäre Datei mit dem Namen "abc.tmp" erstellt und gelöscht, wenn das Programm beendet oder beendet wird .

Wenn Sie die temporäre Datei manuell löschen möchten , können Sie weiterhin File.delete () verwenden.

Grijesh Chauhan
quelle
Warum ist dies die beste Vorgehensweise?
Frans
3

Temporäre Datei wird verwendet, um die weniger wichtigen und temporären Daten zu speichern, die immer gelöscht werden sollten, wenn Ihr System beendet wird. Am besten verwenden Sie dazu File.deleteOnExit ().

Beispielsweise,

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

Im obigen Beispiel wird eine temporäre Datei mit dem Namen "abc.tmp" erstellt und gelöscht, wenn das Programm beendet oder beendet wird.

Juned Ahsan
quelle
-1

Sie können die Datei manuell löschen, bevor Sie den Prozess beenden, wenn Sie möchten. Wenn der Prozess jedoch beendet wird, wird die Datei ebenfalls gelöscht.

Jasper Ketelaar
quelle
2
Nein, es wird nur beim Beenden gelöscht, wenn Sie ausdrücklich anrufendeleteOnExit()
Ian Roberts