Khi nào các tệp tạm thời của Java bị xóa?


92

Giả sử tôi tạo một tệp tạm thời trong Java với phương thức

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

Nếu tôi không gọi delete()phương thức rõ ràng , khi nào tệp sẽ bị xóa?

Theo trực giác, đó có thể là khi JVM kết thúc, hoặc sớm hơn (bởi Trình thu gom rác) hoặc muộn hơn (bởi một số quy trình quét Hệ điều hành).



xin lỗi, tôi chỉ kiểm tra phương thức docs.oracle.com/javase/6/docs/api/java/io/… , không cung cấp câu trả lời. Mô tả dài chỉ xuất hiện trong phương thức có chữ ký dài hơn.
Alphaaa

Câu trả lời:


95

Tệp sẽ không tự động bị xóa khỏi JavaDoc :

Phương pháp này chỉ cung cấp một phần của cơ sở tệp tạm thời. Để sắp xếp tự động xóa tệp được tạo bằng phương pháp này, hãy sử dụng phương thức deleteOnExit ().

Vì vậy, bạn phải gọi deleteOnExit () :

Yêu cầu tệp hoặc thư mục được biểu thị bằng tên đường dẫn trừu tượng này bị xóa khi máy ảo kết thúc.


2
và nếu deleteOnExit được sử dụng, nó sẽ bị xóa "khi máy ảo kết thúc. Các tệp (hoặc thư mục) bị xóa theo thứ tự ngược lại mà chúng đã được đăng ký. Gọi phương pháp này để xóa tệp hoặc thư mục đã được đăng ký để xóa không hiệu lực. Việc xóa sẽ chỉ được cố gắng kết thúc bình thường của máy ảo, như được xác định bởi Đặc tả ngôn ngữ Java. " vì vậy nó không bị xóa ngay cả trên tất cả JVM tồn tại.
EIS

cảm ơn, tôi chỉ kiểm tra phương pháp docs.oracle.com/javase/6/docs/api/java/io/… , không cung cấp câu trả lời. Mô tả dài chỉ xuất hiện trong phương thức có chữ ký dài hơn
Alphaaa

52

Như các câu trả lời khác lưu ý, các tệp tạm thời được tạo bằng File.createTempFile()sẽ không tự động bị xóa trừ khi bạn yêu cầu rõ ràng.

Các chung, cách cầm tay để làm điều này là để gọi .deleteOnExit()trên Fileđối tượng, trong đó sẽ sắp xếp các tập tin để xóa khi JVM chấm dứt. Tuy nhiên, một nhược điểm nhỏ của phương pháp này là nó chỉ hoạt động nếu VM kết thúc bình thường; khi kết thúc bất thường (tức là sự cố máy ảo hoặc buộc phải chấm dứt quy trình máy ảo), tệp có thể vẫn không bị xóa.

Trên các hệ thống Unixish (chẳng hạn như Linux), thực sự có thể có được một giải pháp đáng tin cậy hơn bằng cách xóa tệp tạm thời ngay sau khi mở nó . Điều này hoạt động vì hệ thống tệp Unix cho phép xóa một tệp ( chính xác là hủy liên kết ) trong khi nó vẫn được mở bởi một hoặc nhiều quy trình. Các tệp như vậy có thể được truy cập bình thường thông qua xử lý tệp đang mở và dung lượng chúng chiếm trên đĩa sẽ chỉ được Hệ điều hành thu hồi sau khi quá trình cuối cùng giữ một chốt mở để tệp thoát ra.

Vì vậy, đây là cách đáng tin cậy và di động nhất mà tôi biết để đảm bảo rằng tệp tạm thời sẽ được xóa đúng cách sau khi chương trình thoát ra:

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

Trên hệ thống Unixish, chạy điều này sẽ tạo ra một cái gì đó giống như đầu ra sau:

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.

trong khi trên Windows, đầu ra trông hơi khác một chút:

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.

Tuy nhiên, trong cả hai trường hợp, tệp tạm thời không nên vẫn còn trên đĩa sau khi chương trình kết thúc.


Ps. Trong khi thử nghiệm mã này trên Windows, tôi đã quan sát thấy một thực tế khá ngạc nhiên: rõ ràng, chỉ cần để tệp tạm thời không bị xóa là đủ để giữ cho nó không bị xóa . Tất nhiên, điều này cũng có nghĩa là bất kỳ sự cố nào xảy ra trong khi tệp tạm thời đang được sử dụng sẽ khiến nó không bị xóa, đó chính là điều chúng tôi đang cố gắng tránh ở đây.

AFAIK, cách duy nhất để tránh điều này là đảm bảo rằng tệp tạm thời luôn được đóng bằng cách sử dụng một finallykhối. Tất nhiên, sau đó bạn cũng có thể xóa tệp trong cùng một finallykhối. Tôi không chắc điều gì, nếu có, việc sử dụng .deleteOnExit()thực sự sẽ giúp bạn đạt được điều đó.


1
Câu trả lời chính xác. Một điều quan trọng khác cần lưu ý deleteOnExit(), là nếu nó được gọi thường xuyên (ví dụ, trong một hệ thống sử dụng nhiều tệp tạm thời mới), nó có thể sẽ gây ra rò rỉ bộ nhớ (vì nó phải ghi nhớ tất cả các đường dẫn cần thiết. đã xóa).
Eyal Roth

18

Nếu tôi không gọi delete()phương thức rõ ràng , khi nào tệp sẽ bị xóa?

Nó sẽ không, ít nhất là không bằng Java. Nếu bạn muốn tệp bị xóa khi JVM kết thúc thì bạn cần gọi tmp.deleteOnExit().


5

from: Cách xóa tệp tạm thời trong Java

Tệp tạm thời được sử dụng để lưu trữ dữ liệu tạm thời và ít quan trọng hơn, dữ liệu này sẽ luôn bị xóa khi hệ thống của bạn kết thúc . Cách tốt nhất là sử dụng File.deleteOnExit () để thực hiện.

Ví dụ,

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

Ví dụ trên sẽ tạo một tệp tạm thời có tên “abc.tmp” và xóa nó khi chương trình bị kết thúc hoặc thoát .

Nếu bạn muốn xóa tệp tạm thời theo cách thủ công , bạn vẫn có thể sử dụng File.delete ().


Tại sao đây là phương pháp hay nhất?
Frans

3

Tệp tạm thời được sử dụng để lưu trữ dữ liệu tạm thời và ít quan trọng hơn, dữ liệu này sẽ luôn bị xóa khi hệ thống của bạn kết thúc. Cách tốt nhất là sử dụng File.deleteOnExit () để thực hiện.

Ví dụ,

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

Ví dụ trên sẽ tạo một tệp tạm thời có tên “abc.tmp” và xóa nó khi chương trình bị kết thúc hoặc thoát.


-3

Bạn có thể xóa tệp theo cách thủ công trước khi kết thúc quá trình nếu bạn muốn, tuy nhiên khi quá trình kết thúc, tệp cũng sẽ bị xóa.


3
Không, nó sẽ chỉ bị xóa khi thoát nếu bạn gọi cụ thểdeleteOnExit()
Ian Roberts
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.