Когда удаляются временные файлы Java?

92

Предположим, я создаю временный файл на Java с помощью метода

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

Если я не буду явно называть delete()метод, когда файл будет удален?

Как интуиция, это может быть, когда JVM завершает работу, или раньше (сборщиком мусора), или позже (каким-то процессом очистки операционной системы).

Alphaaa
источник
2
deleteOnExit ()
devnull
извиняюсь, я проверил только метод docs.oracle.com/javase/6/docs/api/java/io/… , который не дает ответа. Полное описание присутствует только в методе с более длинной подписью.
Alphaaa

Ответы:

95

Файл не будет удален автоматически из JavaDoc :

Этот метод предоставляет только часть средства временного файла. Чтобы организовать автоматическое удаление файла, созданного этим методом, используйте метод deleteOnExit ().

Таким образом, вы должны явно вызвать deleteOnExit () :

Запрашивает, чтобы файл или каталог, обозначенные этим абстрактным путем, были удалены при завершении работы виртуальной машины.

Кай
источник
2
и если используется deleteOnExit, он будет удален "при завершении работы виртуальной машины. Файлы (или каталоги) удаляются в порядке, обратном их регистрации. Вызов этого метода для удаления файла или каталога, который уже зарегистрирован для удаления, не имеет Эффект. Удаление будет предпринято только для нормального завершения работы виртуальной машины, как определено в Спецификации языка Java. " поэтому он не удаляется даже на всех существующих JVM.
eis
спасибо, я только проверил метод docs.oracle.com/javase/6/docs/api/java/io/… , который не дает ответа. Длинное описание присутствует только в методе с более длинной подписью
Alphaaa
52

Как отмечают другие ответы, временные файлы, созданные с помощью File.createTempFile(), не будут удалены автоматически, если вы явно не запросите это.

Родовой, переносимый способ сделать это , чтобы позвонить .deleteOnExit()на Fileобъект, который будет планировать файл для удаления , когда виртуальная машина завершается. Однако небольшой недостаток этого метода заключается в том, что он работает только при нормальном завершении работы виртуальной машины; при аварийном завершении (например, сбое виртуальной машины или принудительное завершение процесса виртуальной машины) файл может остаться восстановленным.

В системах 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 я заметил довольно удивительный факт: по-видимому, просто оставить временный файл незакрытым, чтобы предотвратить его удаление . Конечно, это также означает, что любой сбой, происходящий во время использования временного файла, приведет к тому, что он останется не удаленным, чего мы и пытаемся здесь избежать .

AFAIK, единственный способ избежать этого - убедиться, что временный файл всегда закрывается с помощью finallyблока. Конечно, тогда вы могли бы также удалить файл в том же finallyблоке. Я не уверен, что использование .deleteOnExit()действительно поможет вам в этом.

Илмари Каронен
источник
1
Отличный ответ. Еще одна важная вещь, о которой следует отметить deleteOnExit(), заключается в том, что если она вызывается часто (скажем, в системе, которая использует много новых временных файлов), она, вероятно, вызовет утечку памяти (поскольку она должна запомнить все пути, которые должны быть удалено).
Эял Рот
18

Если я не буду явно называть delete()метод, когда файл будет удален?

Этого не будет, по крайней мере, не на Java. Если вы хотите, чтобы файл был удален при завершении работы JVM, вам необходимо позвонить tmp.deleteOnExit().

Ян Робертс
источник
5

из: Как удалить временный файл в Java

Временный файл используется для хранения менее важных и временных данных, которые всегда следует удалять при завершении работы вашей системы . Лучше всего использовать для этого File.deleteOnExit ().

Например,

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

В приведенном выше примере создается временный файл с именем «abc.tmp» и удаляется при завершении или выходе из программы .

Если вы хотите удалить временный файл вручную , вы все равно можете использовать File.delete ().

Гриджеш Чаухан
источник
Почему это лучшая практика?
Frans
3

Временный файл используется для хранения менее важных и временных данных, которые всегда следует удалять при завершении работы вашей системы. Лучше всего использовать для этого File.deleteOnExit ().

Например,

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

В приведенном выше примере создается временный файл с именем «abc.tmp» и удаляется при завершении или выходе программы.

Джунед Ахсан
источник
-3

Вы можете вручную удалить файл перед завершением процесса, если хотите, однако, когда процесс завершится, файл также будет удален.

Джаспер Кетелаар
источник
3
Нет, он будет удален только при выходе, если вы специально позвонитеdeleteOnExit()
Ян Робертс