Xóa tất cả các tệp trong thư mục (nhưng không phải thư mục) - một giải pháp lót


201

Tôi muốn xóa tất cả các tập tin trong thư mục ABC.

Khi tôi thử với FileUtils.deleteDirectory(new File("C:/test/ABC/"));nó cũng xóa thư mục ABC.

Có một giải pháp lót mà tôi có thể xóa các tập tin trong thư mục nhưng không phải thư mục?


2
Đó là bởi vì .deleteDirectory (ngay cả tên ngụ ý nó) được sử dụng để xóa thư mục. Nó sẽ nhận được thư mục trong đó nếu tệp không phải là thư mục.
dùng1534664

Hãy thử tìm các hàm khác trong lớp FileUtils, xóa các tệp thay vì của thư mục.
dùng1534664


1
Tại sao bạn đặc biệt cần một lớp lót? Hiệu suất không thể là tiêu chí, bởi vì bất kỳ phương pháp thư viện của bên thứ 3 nào, sẽ chỉ thực hiện điều đó theo cách đệ quy. Vì vậy, nó sẽ cung cấp cho bạn hiệu suất tương tự?
Rohit Jain

1
Một điều bạn có thể làm là xóa thư mục và sau đó tạo lại nó. Chúng tôi thấy rằng sử dụng rm -rf directory; mkdir directorynhanh hơn sử dụng FileUtils.cleanDirectory.
Joshua Pinter

Câu trả lời:


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

FileUtils.cleanDirectory(directory); 

Có phương pháp này có sẵn trong cùng một tập tin. Điều này cũng sẽ xóa đệ quy tất cả các thư mục con và tệp bên dưới chúng.

Tài liệu: org.apache.commons.io.FileUtils.cleanDirectory


49
Một trong những tốt đẹp, cũng để ngăn chặn mọi người phải tìm kiếm này; đây là phần nhập: nhập org.apache.commons.io.FileUtils;
Paul Gregoire

5
Tôi vẫn phải tìm kiếm lý do tại sao nhập khẩu không thể được tìm thấy. Đó là bởi vì người ta phải tải nó từ apache.org .
Tomáš Zato - Phục hồi Monica

giải pháp khá. Kiểm tra lib này bằng gradle: biên dịch "commons-io: commons-io: +"
Leo Nguyen

1
Phụ thuộc lớp - nhóm biên dịch: 'commons-io', tên: 'commons-io', phiên bản: '2.5'.
Jaydev

Lưu ý, chúng tôi thấy việc gọi điện rm -rf directoryhiệu quả hơn nhiều so với sử dụng FileUtils.cleanDirectory.
Joshua Pinter

267

Ý bạn là như thế nào?

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

Điều này sẽ chỉ xóa các tập tin, không phải thư mục.


65
Đây là câu trả lời tốt hơn, vì nó không sử dụng lib bên ngoài!
AlexWien

10
@amar nhưng ngay cả sau đó: khi có một phương thức tiêu chuẩn, tuyệt đối không có lý do để sử dụng một phương thức bên ngoài làm điều tương tự. Một ngày nào đó anh ta có thể muốn thoát khỏi lib, hoặc lib không còn được hỗ trợ nữa, hoặc không được phép sử dụng lib vì lý do giấy phép, v.v. (Tất cả điều này có thể không phải là vấn đề đối với lib cụ thể này, nhưng áp dụng cho nhiều cái khác)
AlexWien

10
Điều này sẽ không xóa tất cả mọi thứ nếu bạn có thư mục con bên trong thư mục "dir" gốc.
Tiago

2
@TiagoT Đúng, điều này sẽ không xóa các thư mục con không trống.
Peter Lawrey

4
for(File file: dir.listFiles())có lẽ có nghĩa là .... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.

62

Câu trả lời của Peter Lawrey rất hay vì nó đơn giản và không phụ thuộc vào điều gì đặc biệt, và đó là cách bạn nên làm. Nếu bạn cần một cái gì đó loại bỏ các thư mục con và nội dung của chúng, hãy sử dụng đệ quy:

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

Để phụ các thư mục con và nội dung của chúng (một phần câu hỏi của bạn), hãy sửa đổi như sau:

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

Hoặc, vì bạn muốn một giải pháp một dòng:

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

Sử dụng một thư viện bên ngoài cho một nhiệm vụ tầm thường như vậy không phải là một ý tưởng tốt trừ khi bạn cần thư viện này cho một cái gì đó khác, trong trường hợp đó là thích hợp hơn để sử dụng mã hiện có. Dường như bạn đang sử dụng thư viện Apache, vì vậy hãy sử dụng FileUtils.cleanDirectory()phương thức của nó .


1
Mặt khác, nếu không ai là người đầu tiên sử dụng thư viện bên ngoài, thì ít có khả năng những người khác sẽ tìm thấy hành vi tương tự trong thư viện bên ngoài đó, và ít có khả năng họ sẽ nhìn vào đó ... chúng ta không có đủ Không được phát minh ở đây ngoài kia? Nếu thư viện gắn kết và dễ dàng thêm vào dự án của tôi, thì tôi hầu như luôn thích thêm thư viện.
JB Rainsberger

33

Luồng Java 8

Điều này chỉ xóa các tệp từ ABC (thư mục con không được chạm tới):

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

Điều này chỉ xóa các tệp từ ABC (và thư mục con):

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

^ Phiên bản này yêu cầu xử lý IOException


1
Thư mục thứ hai không xóa các thư mục con (đã kiểm tra)
chiều

1
@edwise Có, nó xóa tất cả các tệp khỏi ABC và tất cả các tệp khỏi thư mục con. Tiếng Anh hơi mơ hồ.
Phi tuyến

11

Hoặc để sử dụng điều này trong Java 8:

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

Thật đáng tiếc khi xử lý ngoại lệ là rất cồng kềnh, nếu không nó sẽ là một ...


Làm thế nào để bạn biết rằng tập tin đó một tập tin thực sự và không phải là một thư mục?
Stephan

1
Nó cũng xóa thư mục, vì vậy nó không phải là một giải pháp cho vấn đề từ chủ đề
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

Một giải pháp Luồng Java 8 khác để xóa tất cả nội dung của một thư mục, bao gồm các thư mục con, nhưng không phải chính thư mục đó.

Sử dụng:

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

và mã:

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

Vấn đề với mọi giải pháp truyền phát liên quan đến Files.walk hoặc Files.delete là các phương thức này ném IOException, đây là một vấn đề khó xử lý trong các luồng.

Tôi đã cố gắng tạo ra một giải pháp ngắn gọn hơn có thể.


Thay vào đó, trả về null trong Hàm đi bộ, tốt hơn là trả về một luồng trống (Stream.empty ()). Nó sạch hơn và chức năng luôn trả về một luồng. Null nên tránh khi có thể.
kaba713

Cảm ơn, tôi đã cải thiện câu trả lời với đề xuất của bạn
tặc

2

Để xóa tất cả các tệp khỏi thư mục, hãy nói "C: \ Ví dụ"

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 -rfnhiều hơn performant hơn FileUtils.cleanDirectory.

Không phải là giải pháp một lớp nhưng sau khi đo điểm chuẩn, chúng tôi thấy rằng việc sử dụng rm -rfnhanh hơn nhiều lần so với sử dụng FileUtils.cleanDirectory.

Tất nhiên, nếu bạn có một thư mục nhỏ hoặc đơn giản, điều đó sẽ không thành vấn đề nhưng trong trường hợp của chúng tôi, chúng tôi có nhiều gigabyte và các thư mục con được lồng sâu trong đó sẽ mất hơn 10 phút FileUtils.cleanDirectoryvà chỉ 1 phút với rm -rf.

Đây là triển khai Java thô của chúng tôi để làm điều đó:

// 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;

}

Đáng để thử nếu bạn đang xử lý các thư mục lớn hoặc phức tạp.


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

Nếu bạn muốn xóa tất cả các tập tin loại bỏ

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

tuyên bố nó sẽ làm việc.


0

Tôi nghĩ rằng điều này sẽ hoạt động (dựa trên câu trả lời trước đó của NonlinearFbean):

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

Chúc mừng!

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.