Коли видаляються тимчасові файли Java?


92

Припустимо, я створюю тимчасовий файл на Java за допомогою цього методу

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

Якщо я не називаю delete()метод, коли файл буде видалено?

Як інтуїція, це може бути, коли JVM припиняється, або раніше (Сміттєвим збирачем), або пізніше (яким-небудь процесом підмітання операційної системи).



вибачаючись , я перевірив лише метод 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.

Однак у будь-якому випадку тимчасовий файл не повинен залишатися на диску після закінчення програми.


Ps. Під час тестування цього коду в 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 ().


Чому це найкраща практика?
Франс

3

Тимчасовий файл використовується для зберігання менш важливих і тимчасових даних, які завжди слід видаляти після припинення роботи вашої системи. Найкращою практикою є використання File.deleteOnExit () для цього.

Наприклад,

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

Наведений вище приклад створить тимчасовий файл з назвою “abc.tmp” і видалить його, коли програму буде припинено або закрито.


-3

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


3
Ні, його буде видалено лише при виході, якщо ви спеціально зателефонуєтеdeleteOnExit()
Ян Робертс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.