Kapan file sementara Java dihapus?

92

Misalkan saya membuat file sementara di Java dengan metode

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

Jika saya tidak secara eksplisit memanggil delete()metode ini, kapan file tersebut akan dihapus?

Sebagai intuisi, itu mungkin terjadi ketika JVM berakhir, atau lebih awal (oleh Pengumpul Sampah), atau lebih baru (oleh beberapa proses pembersihan Sistem Operasi).

Alphaaa
sumber
2
deleteOnExit ()
devnull
maaf, saya hanya memeriksa metode docs.oracle.com/javase/6/docs/api/java/io/… , yang tidak memberikan jawabannya. Deskripsi panjang hanya ada dalam metode dengan tanda tangan yang lebih panjang.
Alphaaa

Jawaban:

95

File tidak akan dihapus secara otomatis, dari JavaDoc :

Metode ini hanya menyediakan sebagian dari fasilitas file sementara. Untuk mengatur agar file yang dibuat dengan metode ini dihapus secara otomatis, gunakan metode deleteOnExit ().

Jadi, Anda harus memanggil deleteOnExit () secara eksplisit :

Meminta agar file atau direktori yang ditunjukkan dengan nama jalur abstrak ini dihapus saat mesin virtual berakhir.

Kai
sumber
2
dan jika deleteOnExit digunakan, itu akan dihapus "ketika mesin virtual berhenti. File (atau direktori) dihapus dalam urutan terbalik ketika mereka terdaftar. Memanggil metode ini untuk menghapus file atau direktori yang sudah terdaftar untuk dihapus tidak memiliki efek. Penghapusan akan dilakukan hanya untuk penghentian normal mesin virtual, sebagaimana ditentukan oleh Spesifikasi Bahasa Java. " sehingga tidak terhapus bahkan pada semua JVM yang ada.
eis
terima kasih, saya hanya memeriksa metode docs.oracle.com/javase/6/docs/api/java/io/… , yang tidak memberikan jawabannya. Deskripsi panjang hanya ada dalam metode dengan tanda tangan yang lebih panjang
Alphaaa
52

Sebagai jawaban yang lain mencatat, file-file sementara yang dibuat dengan File.createTempFile()akan tidak dihapus secara otomatis kecuali Anda secara eksplisit memintanya.

Generik, cara yang portabel untuk melakukan ini adalah untuk memanggil .deleteOnExit()pada Fileobjek, yang akan menjadwalkan file untuk penghapusan ketika JVM berakhir. Sedikit kerugian dari metode ini, bagaimanapun, adalah metode ini hanya berfungsi jika VM berhenti secara normal; pada penghentian abnormal (mis. VM crash atau penghentian paksa proses VM), file mungkin tetap tidak dihapus.

Pada sistem Unixish (seperti Linux), sebenarnya mungkin untuk mendapatkan solusi yang lebih andal dengan menghapus file sementara segera setelah membukanya . Ini berfungsi karena sistem file Unix memungkinkan file untuk dihapus (tidak ditautkan , tepatnya) saat masih dibuka oleh satu atau beberapa proses. File tersebut dapat diakses secara normal melalui open filehandle, dan ruang yang mereka tempati pada disk hanya akan diklaim kembali oleh OS setelah proses terakhir memegang pegangan terbuka hingga file keluar.

Jadi, inilah cara paling andal dan portabel yang saya tahu untuk memastikan bahwa file sementara akan dihapus dengan benar setelah program keluar:

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

Pada sistem Unixish, menjalankan ini akan menghasilkan keluaran seperti berikut:

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.

sedangkan di Windows, hasilnya terlihat sedikit berbeda:

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.

Bagaimanapun, bagaimanapun, file temp tidak boleh tetap di disk setelah program berakhir.


Ps. Saat menguji kode ini di Windows, saya mengamati fakta yang agak mengejutkan: tampaknya, hanya membiarkan file temp tidak ditutup sudah cukup untuk mencegahnya dihapus . Tentu saja, ini juga berarti bahwa setiap kerusakan yang terjadi saat file temp digunakan akan menyebabkannya dibiarkan tidak terhapus, yang persis seperti yang kami coba hindari di sini.

AFAIK, satu-satunya cara untuk menghindarinya adalah dengan memastikan bahwa file temp selalu ditutup menggunakan finallyblok. Tentu saja, Anda juga bisa menghapus file di finallyblok yang sama . Saya tidak yakin apa, jika ada, menggunakan yang .deleteOnExit()benar-benar akan membuat Anda lebih dari itu.

Ilmari Karonen
sumber
1
Jawaban yang bagus. Hal penting lainnya yang perlu diperhatikan deleteOnExit(), adalah bahwa jika sering dipanggil (katakanlah, dalam sistem yang menggunakan banyak file sementara baru), itu mungkin akan menyebabkan kebocoran memori (karena harus menghafal semua jalur yang perlu dihapus).
Eyal Roth
18

Jika saya tidak secara eksplisit memanggil delete()metode ini, kapan file tersebut akan dihapus?

Tidak akan, setidaknya tidak dengan Java. Jika Anda ingin file dihapus ketika JVM berakhir maka Anda perlu menelepon tmp.deleteOnExit().

Ian Roberts
sumber
5

dari: Cara menghapus file sementara di Java

File sementara digunakan untuk menyimpan data yang kurang penting dan sementara, yang harus selalu dihapus saat sistem Anda dihentikan . Praktik terbaiknya adalah menggunakan File.deleteOnExit () untuk melakukannya.

Sebagai contoh,

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

Contoh di atas akan membuat file sementara bernama "abc.tmp" dan menghapusnya ketika program dihentikan atau ditutup .

Jika Anda ingin menghapus file temporary secara manual , Anda masih bisa menggunakan File.delete ().

Grijesh Chauhan
sumber
Mengapa praktik terbaik ini?
Frans
3

File sementara digunakan untuk menyimpan data yang kurang penting dan sementara, yang harus selalu dihapus saat sistem Anda dihentikan. Praktik terbaiknya adalah menggunakan File.deleteOnExit () untuk melakukannya.

Sebagai contoh,

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

Contoh di atas akan membuat file sementara bernama "abc.tmp" dan menghapusnya ketika program dihentikan atau ditutup.

Juned Ahsan
sumber
-3

Anda dapat menghapus file secara manual sebelum menghentikan proses jika Anda mau, namun ketika proses dihentikan, file juga akan dihapus.

Jasper Ketelaar
sumber
3
Tidak, itu hanya akan dihapus saat keluar jika Anda secara khusus menelepondeleteOnExit()
Ian Roberts