ไฟล์ชั่วคราว Java ถูกลบเมื่อใด


92

สมมติว่าฉันสร้างไฟล์ชั่วคราวใน Java ด้วยเมธอด

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

ถ้าฉันไม่เรียกใช้delete()เมธอดอย่างชัดเจนไฟล์จะถูกลบเมื่อใด

ตามสัญชาตญาณอาจเกิดขึ้นเมื่อ JVM ยุติการทำงานหรือก่อนหน้านี้ (โดย Garbage Collector) หรือในภายหลัง (โดยกระบวนการกวาดบางระบบปฏิบัติการ)



ฉันขอโทษฉันตรวจสอบเฉพาะเมธอด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อ็อบเจ็กต์ซึ่งจะกำหนดเวลาการลบไฟล์เมื่อ JVM สิ้นสุดลง อย่างไรก็ตามข้อเสียเล็กน้อยของวิธีนี้คือใช้ได้เฉพาะเมื่อ VM ยุติการทำงานตามปกติ ในการยุติที่ผิดปกติ (เช่น VM ขัดข้องหรือบังคับให้ยุติกระบวนการ VM) ไฟล์อาจยังคงถูกลบ

ในระบบ unixish (เช่นลินุกซ์) ก็เป็นไปได้จริงจะได้รับการแก้ปัญหาที่ค่อนข้างน่าเชื่อถือมากขึ้นโดยการลบไฟล์ชั่วคราวทันทีหลังจากที่เปิดมัน สิ่งนี้ใช้ได้ผลเนื่องจากระบบไฟล์ 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.

อย่างไรก็ตามไม่ว่าในกรณีใดไฟล์ temp ไม่ควรอยู่ในดิสก์หลังจากโปรแกรมสิ้นสุดลง


Ps. ขณะที่การทดสอบรหัสนี้ใน Windows ผมสังเกตเห็นความเป็นจริงค่อนข้างน่าประหลาดใจที่เห็นได้ชัดเพียงออกจากไฟล์ชั่วคราว unclosed ก็เพียงพอที่จะให้มันจากการถูกลบ แน่นอนว่านี่หมายความว่าความผิดพลาดใด ๆ ที่เกิดขึ้นในขณะที่มีการใช้งานไฟล์ temp จะทำให้ไฟล์ถูกปล่อยทิ้งซึ่งเป็นสิ่งที่เราพยายามหลีกเลี่ยงที่นี่

AFAIK วิธีเดียวที่จะหลีกเลี่ยงปัญหานี้คือเพื่อให้แน่ใจว่าไฟล์ temp จะถูกปิดโดยใช้finallyบล็อกเสมอ แน่นอนคุณสามารถลบไฟล์ในfinallyบล็อกเดียวกันได้เช่นกัน ฉันไม่แน่ใจว่าถ้ามีอะไรการใช้.deleteOnExit()จะทำให้คุณได้มากกว่านั้น


1
คำตอบที่ดี สิ่งสำคัญอีกอย่างที่ควรทราบdeleteOnExit()ก็คือหากมีการเรียกใช้บ่อย (เช่นในระบบที่ใช้ไฟล์ชั่วคราวใหม่ ๆ จำนวนมาก) อาจทำให้หน่วยความจำรั่ว (เนื่องจากต้องจดจำเส้นทางทั้งหมดที่ต้องมี ลบ)
Eyal Roth

18

ถ้าฉันไม่เรียกใช้delete()เมธอดอย่างชัดเจนไฟล์จะถูกลบเมื่อใด

มันจะไม่อย่างน้อยก็ไม่ใช่โดย Java หากคุณต้องการไฟล์ที่จะลบเมื่อ JVM tmp.deleteOnExit()ยุติแล้วคุณจะต้องโทร


5

from: วิธีลบไฟล์ชั่วคราวใน 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()
Ian Roberts
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.