ลบไฟล์ทั้งหมดในไดเรกทอรี (แต่ไม่ใช่ไดเรกทอรี) - หนึ่งซับโซลูชั่น


201

ฉันต้องการลบไฟล์ทั้งหมดในไดเรกทอรี ABC

เมื่อฉันลองFileUtils.deleteDirectory(new File("C:/test/ABC/"));มันลบโฟลเดอร์ ABC ด้วย

มีวิธีแก้ไขปัญหาหนึ่งซับที่ฉันสามารถลบไฟล์ในไดเรกทอรี แต่ไม่ไดเรกทอรี?


2
นั่นเป็นเพราะ. deletDirectory (แม้แต่ชื่อที่แสดงถึง) จะใช้สำหรับการลบไดเรกทอรี มันจะได้รับไดเรกทอรีมันอยู่ในนั้นถ้าไฟล์ไม่ใช่ไดเรกทอรี
user1534664

ลองค้นหาฟังก์ชันอื่น ๆ ภายในคลาส FileUtils ซึ่งจะลบไฟล์แทนของไดเร็กตอรี่
user1534664


1
ทำไมคุณถึงต้องการซับแบบพิเศษ? ประสิทธิภาพไม่สามารถเป็นเกณฑ์ได้เนื่องจากวิธีการของห้องสมุดบุคคลที่สามจะทำแบบนั้นซ้ำ ๆ เท่านั้น ดังนั้นมันจะให้ประสิทธิภาพเดียวกันกับคุณ?
Rohit Jain

1
สิ่งหนึ่งที่คุณสามารถทำได้คือลบไดเรกทอรีแล้วสร้างมันขึ้นมาใหม่ เราพบว่าการใช้เป็นเร็วกว่าการใช้rm -rf directory; mkdir directory FileUtils.cleanDirectory
Joshua Pinter

คำตอบ:


362
import org.apache.commons.io.FileUtils;

FileUtils.cleanDirectory(directory); 

มีวิธีนี้ในไฟล์เดียวกัน นี่จะเป็นการลบโฟลเดอร์ย่อยและไฟล์ย่อยทั้งหมดซ้ำ

เอกสาร: org.apache.commons.io.FileUtils.cleanDirectory


49
Nice one, เพื่อป้องกันไม่ให้ผู้คนต้องค้นหาสิ่งนี้; นี่คือการนำเข้า: import org.apache.commons.io.FileUtils;
Paul Gregoire

5
ฉันยังต้องค้นหาสาเหตุที่ไม่พบการนำเข้า มันเป็นเพราะหนึ่งต้องดาวน์โหลดได้จาก apache.org
Tomáš Zato - Reinstate Monica

ทางออกที่ดี ตรวจสอบ lib นี้ด้วย gradle: คอมไพล์ "Commons-io: commons-io: +"
Leo Nguyen

1
การพึ่งพา Gradle - กลุ่มคอมไพล์: 'commons-io', ชื่อ: 'commons-io', เวอร์ชัน: '2.5'
Jaydev

หมายเหตุเราพบโทรถูกมากมีประสิทธิภาพมากขึ้นกว่าการใช้rm -rf directory FileUtils.cleanDirectory
Joshua Pinter

267

คุณหมายถึงเป็นอย่างไร

for(File file: dir.listFiles()) 
    if (!file.isDirectory()) 
        file.delete();

นี่จะเป็นการลบไฟล์เท่านั้นไม่ใช่ไดเรกทอรี


65
นี่คือคำตอบที่ดีกว่าเพราะมันไม่ได้ใช้ lib ภายนอก!
AlexWien

10
@ มาร์ แต่ถึงอย่างนั้น: เมื่อมีวิธีมาตรฐานก็ไม่มีเหตุผลใดเลยที่จะใช้วิธีภายนอกซึ่งทำสิ่งเดียวกัน วันหนึ่งเขาอาจต้องการกำจัด lib หรือ lib ไม่ได้รับการสนับสนุนอีกต่อไปหรือไม่ได้รับอนุญาตให้ใช้ lib สำหรับเหตุผลด้านลิขสิทธิ์ ฯลฯ (ทั้งหมดนี้อาจไม่ใช่ปัญหาสำหรับ lib เฉพาะนี้ แต่ใช้กับ อีกหลายรายการ)
AlexWien

10
สิ่งนี้จะล้มเหลวในการลบทุกอย่างถ้าคุณมีไดเรกทอรีย่อยในไดเรกทอรี "dir"
Tiago

2
@TiagoT จริงนี่จะไม่ลบไดเรกทอรีย่อยที่ไม่ว่างเปล่า
Peter Lawrey

4
for(File file: dir.listFiles())อาจมีความหมายว่า .... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.

62

คำตอบของ Peter Lawrey นั้นยอดเยี่ยมเพราะมันง่ายและไม่ขึ้นอยู่กับสิ่งใดเป็นพิเศษและเป็นวิธีที่คุณควรทำ หากคุณต้องการสิ่งที่ลบไดเรกทอรีย่อยและเนื้อหาเช่นกันให้ใช้การสอบถามซ้ำ:

void purgeDirectory(File dir) {
    for (File file: dir.listFiles()) {
        if (file.isDirectory())
            purgeDirectory(file);
        file.delete();
    }
}

ในการสำรองไดเรกทอรีย่อยและเนื้อหาในส่วนของคำถามของคุณให้แก้ไขดังนี้

void purgeDirectoryButKeepSubDirectories(File dir) {
    for (File file: dir.listFiles()) {
        if (!file.isDirectory())
            file.delete();
    }
}

หรือเนื่องจากคุณต้องการโซลูชันบรรทัดเดียว:

for (File file: dir.listFiles())
    if (!file.isDirectory())
        file.delete();

การใช้ไลบรารี่ภายนอกสำหรับงานเล็ก ๆ น้อย ๆ นั้นไม่ใช่ความคิดที่ดีหากคุณไม่ต้องการไลบรารี่นี้เพื่อใช้อย่างอื่นในกรณีนี้คุณควรใช้รหัสที่มีอยู่แล้ว คุณดูเหมือนจะใช้ห้องสมุด Apache อยู่แล้วดังนั้นให้ใช้FileUtils.cleanDirectory()วิธีการของมัน


1
ในทางตรงกันข้ามถ้าไม่มีใครเป็นคนแรกที่ใช้ห้องสมุดภายนอกมันก็มีโอกาสน้อยที่คนอื่นจะคาดหวังว่าจะพบพฤติกรรมที่คล้ายกันในห้องสมุดภายนอกนั้นและมีโอกาสน้อยกว่าที่พวกเขาจะดูที่นั่น ... เรามีไม่เพียงพอ ไม่ได้คิดค้นที่นี่ใช่ไหม หากห้องสมุดมีความเหนียวแน่นและง่ายต่อการเพิ่มลงในโครงการของฉันฉันก็มักจะชอบที่จะเพิ่มห้องสมุด
JB Rainsberger

33

Java 8 Stream

วิธีนี้จะลบเฉพาะไฟล์จากABC (ไดเรกทอรีย่อยจะไม่ถูกแตะต้อง):

Arrays.stream(new File("C:/test/ABC/").listFiles()).forEach(File::delete);

วิธีนี้จะลบเฉพาะไฟล์จากABC (และไดเรกทอรีย่อย):

Files.walk(Paths.get("C:/test/ABC/"))
                .filter(Files::isRegularFile)
                .map(Path::toFile)
                .forEach(File::delete);

^ รุ่นนี้ต้องการการจัดการ IOException


1
อันที่สองไม่ได้ลบไดเรกทอรีย่อย (ทดสอบ)
edwise

1
@edwise ใช่มันจะลบไฟล์ทั้งหมดจาก ABC และไฟล์ทั้งหมดจากไดเรกทอรีย่อย ภาษาอังกฤษค่อนข้างคลุมเครือ
NonlinearFruit

11

หรือจะใช้สิ่งนี้ใน Java 8:

try {
  Files.newDirectoryStream( directory ).forEach( file -> {
    try { Files.delete( file ); }
    catch ( IOException e ) { throw new UncheckedIOException(e); }
  } );
}
catch ( IOException e ) {
  e.printStackTrace();
}

มันเป็นเรื่องน่าเสียดายที่การจัดการข้อยกเว้นมีขนาดใหญ่มากมิฉะนั้นจะเป็นสายการบินเดียว ...


คุณจะรู้ได้อย่างไรว่าไฟล์นั้นเป็นไฟล์จริงและไม่ใช่ไดเรกทอรี
เตฟาน

1
นอกจากนี้ยังลบไดเรกทอรีดังนั้นจึงไม่ใช่วิธีแก้ไขปัญหาจากหัวข้อ
Marx

5
public class DeleteFile {
    public static void main(String[] args) {
        String path="D:\test"; 
        File file = new File(path);
        File[] files = file.listFiles(); 
        for (File f:files) 
        {if (f.isFile() && f.exists) 
            { f.delete();
system.out.println("successfully deleted");
            }else{
system.out.println("cant delete a file due to open or error");
} }  }}

2

โซลูชัน Java 8 Stream อื่นเพื่อลบเนื้อหาทั้งหมดของโฟลเดอร์รวมไดเรกทอรีย่อย แต่ไม่รวมโฟลเดอร์

การใช้งาน:

Path folder = Paths.get("/tmp/folder");
CleanFolder.clean(folder);

และรหัส:

public interface CleanFolder {
    static void clean(Path folder) throws IOException {

        Function<Path, Stream<Path>> walk = p -> {
            try { return Files.walk(p);
        } catch (IOException e) {
            return Stream.empty();
        }};

        Consumer<Path> delete = p -> {
            try {
                Files.delete(p);
            } catch (IOException e) {
            }
        };

        Files.list(folder)
            .flatMap(walk)
            .sorted(Comparator.reverseOrder())
            .forEach(delete);
    }
}

ปัญหาเกี่ยวกับการแก้ปัญหาทุกครั้งที่เกี่ยวข้องกับ Files.walk หรือ Files.delete คือวิธีการเหล่านี้พ่น IOException ซึ่งเป็นความเจ็บปวดในการจัดการกับสตรีม

ฉันพยายามสร้างวิธีแก้ปัญหาที่กระชับที่สุด


แทนที่จะส่งคืนค่า null ในฟังก์ชั่นการเดินจะเป็นการดีกว่าถ้าส่งคืนสตรีมที่ว่างเปล่า (Stream.empty ()) มันสะอาดกว่าและฟังก์ชั่นจะคืนค่าสตรีมเสมอ ควรหลีกเลี่ยงค่าว่างหากเป็นไปได้
kaba713

ขอบคุณฉันปรับปรุงคำตอบด้วยคำแนะนำของคุณ
จี้

2

สำหรับการลบไฟล์ทั้งหมดจากไดเรกทอรีให้พูดว่า "C: \ ตัวอย่าง"

File file = new File("C:\\Example");      
String[] myFiles;    
if (file.isDirectory()) {
    myFiles = file.list();
    for (int i = 0; i < myFiles.length; i++) {
        File myFile = new File(file, myFiles[i]); 
        myFile.delete();
    }
}

2

rm -rfถูกมากมากขึ้น performant FileUtils.cleanDirectoryกว่า

ไม่ได้เป็นทางออกหนึ่งซับ แต่หลังจากการเปรียบเทียบที่กว้างขวางเราพบว่าการใช้เป็นหลายครั้งเร็วกว่าการใช้rm -rfFileUtils.cleanDirectory

แน่นอนถ้าคุณมีไดเรกทอรีขนาดเล็กหรือเรียบง่ายมันจะไม่สำคัญ แต่ในกรณีของเราเรามีหลายกิกะไบต์และไดเรกทอรีย่อยที่ซ้อนกันอย่างลึกซึ้งซึ่งอาจใช้เวลามากกว่า 10 นาทีFileUtils.cleanDirectoryและใช้เวลาเพียง 1 นาทีrm -rfเท่านั้น

ต่อไปนี้เป็นการนำ Java มาใช้อย่างคร่าวๆเพื่อทำสิ่งนี้:

// Delete directory given and all subdirectories and files (i.e. recursively).
//
static public boolean clearDirectory( File file ) throws IOException, InterruptedException {

    if ( file.exists() ) {

        String deleteCommand = "rm -rf " + file.getAbsolutePath();
        Runtime runtime = Runtime.getRuntime();

        Process process = runtime.exec( deleteCommand );
        process.waitFor();

        file.mkdirs(); // Since we only want to clear the directory and not delete it, we need to re-create the directory.

        return true;
    }

    return false;

}

น่าลองถ้าคุณจัดการกับไดเรกทอรีขนาดใหญ่หรือซับซ้อน


1
package com;
import java.io.File;
public class Delete {
    public static void main(String[] args) {

        String files; 
        File file = new File("D:\\del\\yc\\gh");
        File[] listOfFiles = file.listFiles(); 
        for (int i = 0; i < listOfFiles.length; i++) 
        {
            if (listOfFiles[i].isFile()) 
            {
                files = listOfFiles[i].getName();
                System.out.println(files);
                if(!files.equalsIgnoreCase("Scan.pdf"))
                {
                    boolean issuccess=new File(listOfFiles[i].toString()).delete();
                    System.err.println("Deletion Success "+issuccess);
                }
            }
        }
    }
}

หากคุณต้องการลบไฟล์ทั้งหมดลบ

if(!files.equalsIgnoreCase("Scan.pdf"))

คำสั่งมันจะทำงาน


0

ฉันคิดว่ามันจะใช้งานได้ (ตามคำตอบก่อนหน้านี้ของ NonlinearFruit):

Files.walk(Paths.get("C:/test/ABC/"))
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .filter(item -> !item.getPath().equals("C:/test/ABC/"))
                .forEach(File::delete);

ไชโย!

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