file.delete () ส่งคืนเท็จแม้ว่า file.exists (), file.canRead (), file.canWrite (), file.canExecute () ทั้งหมดจะคืนค่าจริง


90

ฉันกำลังพยายามลบไฟล์หลังจากเขียนบางอย่างในไฟล์ด้วยFileOutputStream. นี่คือรหัสที่ฉันใช้เขียน:

private void writeContent(File file, String fileContent) {
    FileOutputStream to;
    try {
        to = new FileOutputStream(file);
        to.write(fileContent.getBytes());
        to.flush();
        to.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

อย่างที่เห็นฉันล้างและปิดสตรีม แต่เมื่อฉันพยายามลบfile.delete()กลับเป็นเท็จ

ฉันจะตรวจสอบก่อนการลบเพื่อดูว่าไฟล์ที่มีอยู่และ: file.exists(), file.canRead(), file.canWrite(), file.canExecute()ผลตอบแทนจริงทั้งหมด หลังจากเรียกวิธีการเหล่านี้ฉันลองfile.delete()และส่งคืนเท็จ

มีอะไรที่ฉันทำผิดหรือเปล่า?


ฉันลืมพูดไปว่าไม่มีข้อยกเว้นใด ๆ เกิดขึ้น
Jenny Smith

แน่ใจหรือไม่ว่าไฟล์นั้นไม่ได้ถูกใช้โดยกระบวนการอื่น? คุณล็อคหรือไม่ มันทำงานร่วมกับ deleteOnExit + ออกหรือไม่
เช่นฉัน

คุณใช้ระบบปฏิบัติการอะไร คุณสามารถลบไฟล์ด้วยตนเองได้หรือไม่? อาจมีบางอย่างที่จับเปิดไฟล์ได้
akarnokd

ฉันจะทราบได้อย่างไรว่ามีการใช้กระบวนการอื่น ฉันไม่ได้ล็อคมัน ฉันไม่สามารถใช้เมธอด deleteOnExit ได้เพราะฉันต้องการลบไฟล์และใช้งานต่อหลังจากนั้นแนวคิดก็คือฉันพยายามปล่อยโฟลเดอร์ชั่วคราวซึ่งใช้ในการจัดเก็บไฟล์จากโฟลเดอร์อื่นเป็นเวลาหนึ่งเซสชัน เมื่อฉันกดปุ่มเปิดบน applycation ของฉันหมายความว่าต้องล้างโฟลเดอร์เพื่อให้มีที่ว่างสำหรับไฟล์อื่น ๆ ถ้าฉันข้ามส่วนเมื่อฉันเขียนในไฟล์นั้นก็โอเคและฉันสามารถลบได้
Jenny Smith

1
คุณช่วยห่อฟลัชและปิดในบล็อกสุดท้ายได้ไหม ฉันรู้ว่าคุณทำสิ่งนี้แล้วและไม่ได้ผล แต่จะเพิ่มความชัดเจนให้กับคำถามของคุณ
bharal

คำตอบ:


101

ข้อบกพร่องอื่นใน Java ฉันแทบจะไม่พบพวกเขาเพียงวินาทีเดียวในอาชีพการงาน 10 ปีของฉัน นี่คือวิธีแก้ปัญหาของฉันอย่างที่คนอื่นพูดถึง ฉันใช้ nether System.gc()แล้ว แต่ในกรณีของฉันมันสำคัญอย่างยิ่ง แปลก? ใช่!

finally
{
    try
    {
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
        System.gc();
    }
    catch (IOException e)
    {
        logger.error(e.getMessage());
        e.printStackTrace();
    }
}

8
แม้ว่าฉันจะไม่ได้เปิดมันด้วยสตรีมประเภทใด ๆ (เพียงแค่ทำ a new File(path)) แต่ฉันก็พบปัญหาเดียวกันและเพิ่มSystem.gc()ก่อนที่จะdelete()ทำให้มันใช้งานได้!
ixM

ไม่ได้แย่สำหรับฉัน ไฟล์ที่ฉันลบไม่ได้เป็นไฟล์ ZIP ของไฟล์ที่ดาวน์โหลดจากไฟล์ ROMURL สิ่งที่ดีคือไฟล์ที่ดาวน์โหลดจะถูกลบ ความคิดใด ๆ ?
Andrea_86

ทำงานให้ฉัน และ @andreadi ฉันไม่เคยใช้ FileChannel.map ในรหัสของฉัน ดูเหมือนว่าข้อผิดพลาดนี้จะถูกปิดโดยไม่สามารถแก้ไขได้ซึ่งทำให้ฉันไม่เชื่อเพราะSystem.gcเคล็ดลับใช้ได้ทุกครั้ง
Adam Burley

Single gc () อาจไม่ช่วยSystem.gc(); result = file.delete(); if (!result){ Thread.sleep(100); System.gc(); result = file.delete(); }
note-jj

ว้าวขอบคุณสำหรับการโพสต์วิธีแก้ปัญหาของคุณสิ่งนี้ช่วยฉันได้มาก! ฉันประสบปัญหา "ไม่สามารถลบไฟล์ได้" หลังจากการย้ายจาก JDK7 เป็น JDK9 ทำงานได้ดีกับ JDK7 ไม่ทำงานกับ JDK9 อีกต่อไป สุดยอดของคุณด้วยการโทร System.gc () หลังจากการโทรของ [... ]. close () แก้ไขพฤติกรรมแปลก ๆ นี้! ไม่เคยคิดเรื่องนี้ออกมา ... ฉันหมายถึงทำไมต้องเป็น Java ทำไม?
Ulathar

48

มันค่อนข้างแปลกที่เคล็ดลับที่ใช้ได้ผล BufferedReaderสิ่งที่เป็นเมื่อฉันได้อ่านก่อนหน้านี้เนื้อหาของไฟล์ที่ผมใช้ หลังจากอ่านฉันก็ปิดบัฟเฟอร์

ในขณะเดียวกันฉันเปลี่ยนและตอนนี้ฉันกำลังอ่านเนื้อหาโดยใช้ไฟล์ FileInputStreamไฟล์. หลังจากอ่านจบฉันก็ปิดสตรีม และตอนนี้ก็ใช้งานได้แล้ว

ปัญหาคือฉันไม่มีคำอธิบายสำหรับเรื่องนี้

ฉันไม่รู้BufferedReaderและFileOutputStreamเข้ากันไม่ได้


4
ฉันจะเถียงว่ามันเป็นข้อผิดพลาดแล้ว: java.sun.com/javase/6/docs/api/java/io/… มันบอกว่าในนั้นเมธอดควรปิดสตรีมและทรัพยากรใด ๆ ที่เกี่ยวข้อง ฉันมักจะชอบปิดสตรีมทั้งหมดในลำดับกลับหัว (รายการสุดท้ายที่จะเปิดคือรายการแรกที่จะปิด) โดยใช้ IOUtils.closeQuietly แต่มีแนวโน้มที่จะมากเกินไป
Ravi Wallau

2
ฉันมีปัญหานี้แน่นอนฉันและฉันคิดว่าฉันจะบ้า ขอบคุณสำหรับการแก้ปัญหา!
Electrons_Ahoy

14
เป็นปี 2011 กับ JDK 7 และปัญหายังไม่ได้รับการแก้ไข ฉันดีใจมากที่ได้พบกระทู้นี้ - ฉันคิดไม่ออกว่าเกิดอะไรขึ้น ...
เดวิด

ฉันมีปัญหาที่น่ารำคาญมากกับไฟล์ที่ฉันอ่านและปิดแล้วพยายามลบ ไม่มีอะไรที่กล่าวถึงที่นี่ช่วย หลังจากนั้นหนึ่งชั่วโมงฉันพบว่ามันเป็นแค่สิทธิ์ของไฟล์เนื่องจากไฟล์ถูกสร้างโดยผู้ใช้รายอื่น :-D
runholen

เพียงแค่แทงในที่มืด ... คุณสามารถโทรfinalize()เพื่อให้แน่ใจว่ามีการล้างข้อมูลหรือไม่? หรืออาจจะตั้งto = null? ดูบังคับ Finalization และการเก็บขยะ
jww

19

ฉันลองสิ่งง่ายๆนี้และดูเหมือนว่าจะได้ผล

file.setWritable(true);
file.delete();

มันใช้ได้กับฉัน

หากไม่ได้ผลให้ลองรันแอปพลิเคชัน Java ของคุณด้วย sudo ถ้าบน linux และในฐานะผู้ดูแลระบบเมื่ออยู่บน windows เพียงเพื่อให้แน่ใจว่า Java มีสิทธิ์ในการเปลี่ยนแปลงคุณสมบัติของไฟล์


1
สำหรับปัญหานี้; คนทั่วไปมักพูดถึงการตั้งค่าการอ้างอิงเป็น null หรือเรียก system.gc (); แต่สำหรับฉันแม้ว่าไฟล์รีสตาร์ทเซิร์ฟเวอร์จะไม่ถูกลบ !! แต่ file.setWritable (true); เพิ่งทำงาน ..
Deepak Singhal

6

ก่อนที่จะพยายามลบ / เปลี่ยนชื่อไฟล์ใด ๆ คุณต้องแน่ใจว่าผู้อ่านหรือผู้เขียนทั้งหมด (เช่น: BufferedReader/ InputStreamReader/BufferedWriter ) ปิดอย่างถูกต้อง

เมื่อคุณพยายามอ่าน / เขียนข้อมูลของคุณจาก / ไปยังไฟล์ไฟล์จะถูกยึดไว้โดยกระบวนการและจะไม่ถูกปล่อยจนกว่าการเรียกใช้โปรแกรมจะเสร็จสิ้น หากคุณต้องการดำเนินการลบ / เปลี่ยนชื่อก่อนที่โปรแกรมจะสิ้นสุดคุณต้องใช้close()วิธีการที่มาพร้อมกับjava.io.*คลาส


1
นี่เป็นเรื่องจริงบน Windows เท่านั้น ใน O / S จริงคุณสามารถลบและเปลี่ยนชื่อไฟล์ที่เปิดอยู่ได้
Archie

3

ตามที่ Jon Skeet แสดงความคิดเห็นคุณควรปิดไฟล์ของคุณในบล็อก {... } สุดท้ายเพื่อให้แน่ใจว่าไฟล์นั้นปิดอยู่เสมอ และแทนที่จะกลืนข้อยกเว้นด้วย e.printStackTrace เพียงแค่อย่าจับและเพิ่มข้อยกเว้นลงในลายเซ็นของวิธีการ หากคุณทำไม่ได้ด้วยเหตุผลใด ๆ อย่างน้อยก็ทำสิ่งนี้:

catch(IOException ex) {
    throw new RuntimeException("Error processing file XYZ", ex);
}

ตอนนี้คำถาม # 2:

จะเกิดอะไรขึ้นถ้าคุณทำสิ่งนี้:

...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...

คุณจะสามารถลบไฟล์ได้หรือไม่?

นอกจากนี้ไฟล์จะถูกล้างเมื่อปิด ฉันใช้ IOUtils.closeQuietly (... ) ดังนั้นฉันจึงใช้วิธีการล้างเพื่อให้แน่ใจว่าเนื้อหาของไฟล์อยู่ในนั้นก่อนที่ฉันจะพยายามปิด (IOUtils.closeQuietly ไม่ทิ้งข้อยกเว้น) สิ่งนี้:

...
try {
    ...
    to.flush();
} catch(IOException ex) {
    throw new CannotProcessFileException("whatever", ex);
} finally {
    IOUtils.closeQuietly(to);
}

ดังนั้นฉันจึงรู้ว่ามีเนื้อหาของไฟล์อยู่ในนั้น เป็นเรื่องปกติสำหรับฉันที่เนื้อหาของไฟล์จะถูกเขียนขึ้นและไม่ใช่ว่าไฟล์นั้นสามารถปิดได้หรือไม่มันไม่สำคัญว่าไฟล์นั้นจะปิดหรือไม่ ในกรณีของคุณเป็นเรื่องสำคัญฉันขอแนะนำให้ปิดไฟล์ด้วยตัวเองและปฏิบัติตามข้อยกเว้นใด ๆ ตาม


ฉันลองสิ่งแรก - ปิดสตรีมเอาต์พุตในบล็อกสุดท้าย และมันไม่ได้ผล จะเกิดอะไรขึ้นถ้าฉันพยายามอ่านหลังจากนั้นฉันได้รับข้อความแจ้งว่าสตรีมถูกปิด เมื่อสลับและอ่านไฟล์ด้วย FileInputReader ไม่มีสิ่ง "ไม่ดี" ที่อธิบายไว้ข้างต้นเกิดขึ้น
Jenny Smith

2

ไม่มีเหตุผลใดที่คุณไม่ควรลบไฟล์นี้ ฉันจะดูว่าใครมีการระงับไฟล์นี้ ใน unix / linux คุณสามารถใช้ยูทิลิตี้ lsof เพื่อตรวจสอบว่ากระบวนการใดมีการล็อกไฟล์ ใน windows คุณสามารถใช้ process explorer

สำหรับ lsof มันง่ายเหมือนพูดว่า:

lsof /path/and/name/of/the/file

สำหรับ process explorer คุณสามารถใช้เมนูค้นหาและป้อนชื่อไฟล์เพื่อแสดงแฮนเดิลซึ่งจะชี้ให้คุณเห็นกระบวนการล็อกไฟล์

นี่คือรหัสบางส่วนที่ทำในสิ่งที่ฉันคิดว่าคุณต้องทำ:

FileOutputStream to;

try {
    String file = "/tmp/will_delete.txt";
    to = new FileOutputStream(file );
    to.write(new String("blah blah").getBytes());
    to.flush();
    to.close();
    File f = new File(file);
    System.out.print(f.delete());
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

มันใช้งานได้ดีบน OS X ฉันยังไม่ได้ทดสอบบน windows แต่ฉันสงสัยว่ามันน่าจะใช้ได้กับ Windows ฉันจะยอมรับว่ามีพฤติกรรมที่ไม่คาดคิดบางอย่างในการจัดการไฟล์ WRT ของ Windows


1
สำหรับ Windows, คุณสามารถดาวน์โหลดฟรีกระบวนการสำรวจจาก MS: technet.microsoft.com/en-us/sysinternals/bb896653.aspx
akarnokd

2

หากคุณกำลังทำงานใน Eclipse IDE นั่นอาจหมายความว่าคุณไม่ได้ปิดไฟล์ในการเรียกใช้แอปพลิเคชันก่อนหน้านี้ เมื่อฉันมีข้อความแสดงข้อผิดพลาดเดียวกันกับการพยายามลบไฟล์นั่นคือเหตุผล ดูเหมือนว่า Eclipse IDE จะไม่ปิดไฟล์ทั้งหมดหลังจากการยุติแอปพลิเคชัน


1

หวังว่านี่จะช่วยได้ ฉันพบปัญหาที่คล้ายกันซึ่งฉันไม่สามารถลบไฟล์ของฉันได้หลังจากที่รหัส java ของฉันทำสำเนาเนื้อหาไปยังโฟลเดอร์อื่น หลังจาก googling อย่างกว้างขวางฉันได้ประกาศตัวแปรที่เกี่ยวข้องกับการดำเนินการไฟล์ทุกไฟล์อย่างชัดเจนและเรียกเมธอด close () ของอ็อบเจ็กต์การดำเนินการไฟล์แต่ละไฟล์และตั้งค่าเป็น NULL จากนั้นมีฟังก์ชั่นที่เรียกว่า System.gc () ซึ่งจะล้างการแมปไฟล์ i / o (ฉันไม่แน่ใจฉันแค่บอกสิ่งที่ได้รับบนเว็บไซต์)

นี่คือรหัสตัวอย่างของฉัน:

public void start() {
    File f = new File(this.archivePath + "\\" + this.currentFile.getName());
    this.Copy(this.currentFile, f);

    if(!this.currentFile.canWrite()){
        System.out.println("Write protected file " +
           this.currentFile.getAbsolutePath());

        return;
    }


    boolean ok = this.currentFile.delete();
    if(ok == false){
        System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
        return;
    }
}

private void Copy(File source, File dest) throws IOException {
    FileInputStream fin;
    FileOutputStream fout;
    FileChannel cin = null, cout = null;
    try {
        fin = new FileInputStream(source);
        cin = fin.getChannel();
        fout = new FileOutputStream(dest);
        cout = fout.getChannel();

        long size = cin.size();
        MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);

        cout.write(buf);
        buf.clear();
        buf = null;

        cin.close();
        cin = null;

        fin.close();
        fin = null;

        cout.close();
        cout = null;

        fout.close();
        fout = null;

        System.gc();

    } catch (Exception e){
        this.message = e.getMessage();
        e.printStackTrace();
    }
}

1

คำตอบคือเมื่อคุณโหลดไฟล์คุณต้องใช้วิธีการ "ปิด" ในโค้ดบรรทัดใดก็ได้ที่ใช้ได้กับฉัน


0

มีปัญหาครั้งหนึ่งใน Ruby โดยที่ไฟล์ใน windows จำเป็นต้องมี "fsync" เพื่อให้สามารถเปิดและอ่านไฟล์ใหม่ได้หลังจากเขียนและปิดไฟล์ บางทีนี่อาจเป็นการแสดงออกที่คล้ายกัน (และถ้าเป็นเช่นนั้นฉันคิดว่าเป็นข้อผิดพลาดของ windows จริงๆ)


0

ไม่มีวิธีแก้ปัญหาใดที่ระบุไว้ที่นี่ได้ผลในสถานการณ์ของฉัน วิธีแก้ปัญหาของฉันคือใช้ while loop พยายามลบไฟล์โดยมีขีด จำกัด 5 วินาที (กำหนดค่าได้) เพื่อความปลอดภัย

File f = new File("/path/to/file");

int limit = 20; //Only try for 5 seconds, for safety
while(!f.delete() && limit > 0){
    synchronized(this){
        try {
            this.wait(250); //Wait for 250 milliseconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    limit--;
}

การใช้ลูปด้านบนทำงานได้โดยไม่ต้องทำการรวบรวมขยะด้วยตนเองหรือตั้งค่าสตรีมเป็นโมฆะเป็นต้น


คุณใช้อะไร? หากคุณสามารถเข้าถึง STREAMS ได้ให้ปิดมันจะใช้งานได้ แต่ถ้าไฟล์นั้น "อยู่แล้ว" ถูกล็อกแสดงว่าคุณมีปัญหา
marcolopes

1
-1 การวนซ้ำในโค้ดของคุณเพื่อลบไฟล์ไม่ใช่ความคิดที่ดี ทำไมไม่ใช้ตัวเลือก gc () ที่ใช้งานได้
bharal

ประกาศ @bharal ฉันระบุไว้ข้างต้นว่าไม่มีโซลูชันอื่นใด (รวมถึง gc ()) ที่ใช้ได้ในกรณีเฉพาะของฉัน แม้ว่าฉันจะเห็นด้วยกับการใช้ while loop ไม่เหมาะ แต่ก็อาจเป็นวิธีแก้ปัญหาที่เหมาะสมในบางสถานการณ์ การเพิ่มการตรวจสอบเพิ่มเติมให้กับโค้ดด้านบนเช่นตัวแปรการหมดเวลาหรือการวนซ้ำสูงสุดจะเป็นวิธีที่ดีในการทำให้ลูป while ปลอดภัยยิ่งขึ้น
etech

@etech หากไฟล์ของคุณไม่เคยมีอยู่แสดงว่าคุณเพิ่งสร้างลูปที่ไม่มีที่สิ้นสุด
bharal

0

ปัญหาอาจเป็นไปได้ว่าไฟล์ยังคงถูกมองว่าเปิดและล็อกโดยโปรแกรม หรืออาจเป็นส่วนประกอบจากโปรแกรมของคุณที่เปิดไว้ดังนั้นคุณต้องแน่ใจว่าคุณใช้dispose()วิธีการนี้เพื่อแก้ปัญหานั้น กล่าวคือJFrame frame; .... frame.dispose();


0

คุณต้องปิดสตรีมทั้งหมดหรือใช้บล็อกลองใช้กับทรัพยากร

static public String head(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException
{
    final String readLine;
    try (FileInputStream fis = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
            LineNumberReader lnr = new LineNumberReader(isr))
    {
        readLine = lnr.readLine();
    }
    return readLine;
}

0

หาก file.delete () ส่งเป็นเท็จในกรณีส่วนใหญ่ที่จับ Bufferedreader ของคุณจะไม่ถูกปิด เพียงแค่ปิดและดูเหมือนว่าจะทำงานสำหรับฉันตามปกติ


0

ฉันมีปัญหาเดียวกันใน Windows ฉันเคยอ่านไฟล์ใน scala ทีละบรรทัดด้วย

Source.fromFile(path).getLines()

ตอนนี้ฉันอ่านโดยรวมด้วย

import org.apache.commons.io.FileUtils._

// encoding is null for platform default
val content=readFileToString(new File(path),null.asInstanceOf[String])

ซึ่งจะปิดไฟล์อย่างถูกต้องหลังจากอ่านและตอนนี้

new File(path).delete

ได้ผล


0

สำหรับ Eclipse / NetBeans

รีสตาร์ท IDE ของคุณและเรียกใช้รหัสของคุณอีกครั้งนี่เป็นเพียงเคล็ดลับเท่านั้นที่ใช้ได้ผลสำหรับฉันหลังจากต่อสู้มานานหนึ่งชั่วโมง

นี่คือรหัสของฉัน:

File file = new File("file-path");
if(file.exists()){
  if(file.delete()){
     System.out.println("Delete");
  }
  else{

       System.out.println("not delete");
  }
}

เอาท์พุต:

ลบ


0

อีกกรณีหนึ่งที่อาจเกิดขึ้นได้: ถ้าคุณอ่าน / เขียนไฟล์ JAR ผ่านURLและในภายหลังให้ลองลบไฟล์เดียวกันภายในเซสชัน JVM เดียวกัน

File f = new File("/tmp/foo.jar");
URL j = f.toURI().toURL();

URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
URLConnection c = u.openConnection();

// open a Jar entry in auto-closing manner
try (InputStream i = c.getInputStream()) {

    // just read some stuff; for demonstration purposes only
    byte[] first16 = new byte[16];
    i.read(first16);
    System.out.println(new String(first16));
}

// ...

// i is now closed, so we should be good to delete the jar; but...
System.out.println(f.delete());     // says false!

เหตุผลคือตรรกะการจัดการไฟล์ JAR ภายในของ Java มีแนวโน้มที่จะแคชJarFileรายการ:

// inner class of `JarURLConnection` that wraps the actual stream returned by `getInputStream()`

class JarURLInputStream extends FilterInputStream {
    JarURLInputStream(InputStream var2) {
        super(var2);
    }

    public void close() throws IOException {
        try {
            super.close();
        } finally {

            // if `getUseCaches()` is set, `jarFile` won't get closed!

            if (!JarURLConnection.this.getUseCaches()) {
                JarURLConnection.this.jarFile.close();
            }
        }
    }
}

และแต่ละอันJarFile(แต่เป็นZipFileโครงสร้างพื้นฐาน) จะถือแฮนเดิลของไฟล์ตั้งแต่เวลาสร้างจนถึงclose()เรียกใช้:

public ZipFile(File file, int mode, Charset charset) throws IOException {
    // ...

    jzfile = open(name, mode, file.lastModified(), usemmap);

    // ...
}

// ...

private static native long open(String name, int mode, long lastModified,
                                boolean usemmap) throws IOException;

มีคำอธิบายที่ดีในการเป็นปัญหา NetBeans นี้


เห็นได้ชัดว่ามีสองวิธีในการ "แก้ไข" สิ่งนี้:

  • คุณสามารถปิดใช้งานการแคชไฟล์ JAR - สำหรับปัจจุบันURLConnectionหรือสำหรับอนาคตทั้งหมดURLConnection(ทั่วโลก) ในเซสชัน JVM ปัจจุบัน:

    URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
    URLConnection c = u.openConnection();
    
    // for only c
    c.setUseCaches(false);
    
    // globally; for some reason this method is not static,
    // so we still need to access it through a URLConnection instance :(
    c.setDefaultUseCaches(false);
    
  • [คำเตือนแฮ็ก!]คุณสามารถล้างJarFileแคชออกจากแคชด้วยตนเองเมื่อดำเนินการเสร็จสิ้น ตัวจัดการแคชsun.net.www.protocol.jar.JarFileFactoryเป็นแพ็กเกจส่วนตัว แต่เวทมนตร์สะท้อนบางอย่างสามารถทำให้งานสำเร็จสำหรับคุณ:

    class JarBridge {
    
        static void closeJar(URL url) throws Exception {
    
            // JarFileFactory jarFactory = JarFileFactory.getInstance();
            Class<?> jarFactoryClazz = Class.forName("sun.net.www.protocol.jar.JarFileFactory");
            Method getInstance = jarFactoryClazz.getMethod("getInstance");
            getInstance.setAccessible(true);
            Object jarFactory = getInstance.invoke(jarFactoryClazz);
    
            // JarFile jarFile = jarFactory.get(url);
            Method get = jarFactoryClazz.getMethod("get", URL.class);
            get.setAccessible(true);
            Object jarFile = get.invoke(jarFactory, url);
    
            // jarFactory.close(jarFile);
            Method close = jarFactoryClazz.getMethod("close", JarFile.class);
            close.setAccessible(true);
            //noinspection JavaReflectionInvocation
            close.invoke(jarFactory, jarFile);
    
            // jarFile.close();
            ((JarFile) jarFile).close();
        }
    }
    
    // and in your code:
    
    // i is now closed, so we should be good to delete the jar
    JarBridge.closeJar(j);
    System.out.println(f.delete());     // says true, phew.
    

โปรดทราบ:ทั้งหมดนี้ใช้ Java 8 codebase ( 1.8.0_144); อาจใช้ไม่ได้กับเวอร์ชันอื่น / ที่ใหม่กว่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.