Quand les fichiers temporaires Java sont-ils supprimés?

92

Supposons que je crée un fichier temporaire en Java avec la méthode

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

Si je n'appelle pas explicitement le delete() méthode, quand le fichier sera-t-il supprimé?

Par intuition, cela peut être lorsque la JVM se termine, ou plus tôt (par le garbage collector), ou plus tard (par un processus de balayage du système d'exploitation).

Alphaaa
la source
2
deleteOnExit ()
devnull
mes excuses, je n'ai vérifié que la méthode docs.oracle.com/javase/6/docs/api/java/io/… , qui ne fournit pas de réponse. La description longue n'est présente que dans la méthode avec la signature la plus longue.
Alphaaa

Réponses:

95

Le fichier ne sera pas supprimé automatiquement du JavaDoc :

Cette méthode ne fournit qu'une partie d'une fonction de fichier temporaire. Pour faire en sorte qu'un fichier créé par cette méthode soit supprimé automatiquement, utilisez la méthode deleteOnExit ().

Vous devez donc appeler explicitement deleteOnExit () :

Demande que le fichier ou le répertoire désigné par ce chemin abstrait soit supprimé lorsque la machine virtuelle s'arrête.

Kai
la source
2
et si deleteOnExit est utilisé, il sera supprimé "à la fin de la machine virtuelle. Les fichiers (ou répertoires) sont supprimés dans l'ordre inverse de leur enregistrement. L'appel de cette méthode pour supprimer un fichier ou un répertoire déjà enregistré pour la suppression n'a pas . La suppression ne sera tentée que pour l'arrêt normal de la machine virtuelle, tel que défini par la spécification du langage Java. " il n'est donc pas supprimé même sur tous les JVM existants.
Eis
merci, je n'ai vérifié que la méthode docs.oracle.com/javase/6/docs/api/java/io/… , qui ne fournit pas la réponse. La description longue n'est présente que dans la méthode avec la signature la plus longue
Alphaaa
52

Comme le notent les autres réponses, les fichiers temporaires créés avec neFile.createTempFile() seront pas supprimés automatiquement sauf si vous le demandez explicitement.

La manière générique et portable de faire cela est d'appeler .deleteOnExit()leFile objet, qui planifiera la suppression du fichier à la fin de la JVM. Un léger inconvénient de cette méthode, cependant, est qu'elle ne fonctionne que si la VM s'arrête normalement; en cas d'arrêt anormal (c'est-à-dire une panne de machine virtuelle ou une interruption forcée du processus de machine virtuelle), le fichier peut rester non supprimé.

Sur les systèmes Unixish (tels que Linux), il est en fait possible d'obtenir une solution un peu plus fiable en supprimant le fichier temporaire immédiatement après son ouverture . Cela fonctionne car les systèmes de fichiers Unix permettent la suppression d'un fichier ( dissocié , pour être précis) alors qu'il est toujours maintenu ouvert par un ou plusieurs processus. Ces fichiers sont normalement accessibles via le descripteur de fichier ouvert, et l'espace qu'ils occupent sur le disque ne sera récupéré par le système d'exploitation qu'après la sortie du dernier processus détenant un descripteur ouvert du fichier.

Voici donc le moyen le plus fiable et le plus portable que je connaisse pour m'assurer qu'un fichier temporaire sera correctement supprimé après la fermeture du programme:

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

Sur un système Unixish, exécuter ceci devrait produire quelque chose comme la sortie suivante:

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.

alors que sous Windows, la sortie est légèrement différente:

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.

Dans les deux cas, cependant, le fichier temporaire ne doit pas rester sur le disque après la fin du programme.


Ps. En testant ce code sous Windows, j'ai observé un fait assez surprenant: apparemment, le simple fait de laisser le fichier temporaire non fermé suffit à l'empêcher d'être supprimé . Bien sûr, cela signifie également que tout crash qui se produit pendant l'utilisation du fichier temporaire le laissera non supprimé, ce que nous essayons d' éviter ici.

AFAIK, le seul moyen d'éviter cela est de s'assurer que le fichier temporaire est toujours fermé à l'aide d'un finallybloc. Bien sûr, vous pouvez tout aussi bien supprimer le fichier dans le même finallybloc. Je ne suis pas sûr de ce que l'utilisation, le cas échéant, vous .deleteOnExit()apporterait réellement.

Ilmari Karonen
la source
1
Très bonne réponse. Une autre chose importante à noter deleteOnExit(), c'est que s'il est appelé fréquemment (par exemple, dans un système qui utilise beaucoup de nouveaux fichiers temporaires), cela provoquera probablement une fuite de mémoire (car il doit mémoriser tous les chemins qui doivent être supprimé).
Eyal Roth
18

Si je n'appelle pas explicitement ladelete() méthode, quand le fichier sera-t-il supprimé?

Ce ne sera pas le cas, du moins pas par Java. Si vous souhaitez que le fichier soit supprimé à la fin de la JVM, vous devez appeler tmp.deleteOnExit().

Ian Roberts
la source
5

from: Comment supprimer un fichier temporaire en Java

Le fichier temporaire est utilisé pour stocker les données les moins importantes et temporaires, qui doivent toujours être supprimées lorsque votre système est arrêté . La meilleure pratique consiste à utiliser File.deleteOnExit () pour le faire.

Par exemple,

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

L'exemple ci-dessus créera un fichier temporaire nommé «abc.tmp» et le supprimera lorsque le programme est arrêté ou quitté .

Si vous souhaitez supprimer le fichier temporaire manuellement , vous pouvez toujours utiliser File.delete ().

Grijesh Chauhan
la source
Pourquoi cette meilleure pratique?
Frans
3

Le fichier temporaire est utilisé pour stocker les données les moins importantes et temporaires, qui doivent toujours être supprimées lorsque votre système est arrêté. La meilleure pratique consiste à utiliser File.deleteOnExit () pour le faire.

Par exemple,

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

L'exemple ci-dessus créera un fichier temporaire nommé «abc.tmp» et le supprimera lorsque le programme est arrêté ou quitté.

Juned Ahsan
la source
-3

Vous pouvez supprimer manuellement le fichier avant de terminer le processus si vous le souhaitez, mais lorsque le processus est terminé, le fichier sera également supprimé.

Jasper Ketelaar
la source
3
Non, il ne sera supprimé qu'à la sortie si vous appelez spécifiquementdeleteOnExit()
Ian Roberts