Làm thế nào để xóa toàn bộ thư mục và nội dung?


185

Tôi muốn người dùng ứng dụng của tôi có thể xóa thư mục DCIM (nằm trên thẻ SD và chứa các thư mục con).

Điều này có thể, nếu vậy làm thế nào?


1
khác với phương pháp xóa từ dưới lên đệ quy?
Sarwar Erfan

Nếu bạn có một thư mục rất lớn hoặc phức tạp, bạn nên sử dụng rm -rf directorythay vì FileUtils.deleteDirectory. Sau khi điểm chuẩn chúng tôi thấy nó nhanh hơn nhiều lần. Kiểm tra một triển khai mẫu tại đây: stackoverflow.com/a/58421350/293280
Joshua Pinter

Câu trả lời:


299

Hãy để tôi nói cho bạn điều đầu tiên bạn không thể xóa thư mục DCIM vì đây là thư mục hệ thống. Khi bạn xóa thủ công trên điện thoại, nó sẽ xóa nội dung của thư mục đó, nhưng không xóa thư mục DCIM. Bạn có thể xóa nội dung của nó bằng cách sử dụng phương pháp dưới đây:

Cập nhật theo nhận xét

File dir = new File(Environment.getExternalStorageDirectory()+"Dir_name_here"); 
if (dir.isDirectory()) 
{
    String[] children = dir.list();
    for (int i = 0; i < children.length; i++)
    {
       new File(dir, children[i]).delete();
    }
}

3
Làm thế nào để tôi khai báo dir là gì?
Người mới bắt đầu

Về cơ bản, tôi đang cố gắng xóa tất cả các ảnh nên không quan trọng là DCIM không bị xóa miễn là các ảnh đó ... vì vậy, ngay cả việc xóa 100MEDIA thư mục trong này sẽ thực hiện công việc
Người mới bắt đầu

1
bạn phải khai báo thư mục bằng cách sử dụng đường dẫn của thư mục dicm: sử dụng tệp r = file (path);
chikka.anddev

3
đã sử dụng Tệp dir = Tệp mới (Môi trường.getExternalStorageDirectory () + "/ DCIM / 100MEDIA");
Người mới bắt đầu

1
@chiragshah Sau khi xóa một thư mục và tạo lại thư mục dẫn đến việc tạo một tệp không xác định có cùng tên thư mục được đề cập. Và nếu tôi đang cố truy cập vào tệp đó thì nó sẽ ném ngoại lệ như Tài nguyên hoặc thiết bị bận. Tôi cũng đã kiểm tra Thuộc tính của tệp nơi tôi tìm thấy Chữ ký MD5: Lỗi hoạt động
sha

529

Bạn có thể xóa các tệp và thư mục đệ quy như thế này:

void deleteRecursive(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory())
        for (File child : fileOrDirectory.listFiles())
            deleteRecursive(child);

    fileOrDirectory.delete();
}

21
Tôi đã không thực hiện các bài kiểm tra nào về hiệu quả, nhưng tôi tin rằng tôi mạnh hơn. chirag's sẽ hoạt động cho trường hợp cụ thể của thư mục DCIM, trong đó các thư mục trong DCIM chỉ nên chứa các tệp (tức là các thư mục trong DCIM thường không chứa bất kỳ thư mục con nào). Phiên bản của tôi sẽ xóa các thư mục được lồng vào bất kỳ độ sâu nào. Có khả năng người dùng đã sửa đổi nội dung của thẻ SD của mình để DCIM chứa các thư mục được lồng sâu hơn (ví dụ DCIM\foo\bar\pic.jpg), trong trường hợp đó, mã của chirag sẽ thất bại.
teedyay

2
Một câu hỏi mà một đồng nghiệp đã hỏi tôi: Điều gì xảy ra nếu một thư mục có một liên kết tượng trưng trên chính nó và bạn thực thi đoạn mã này?
p4u144

1
@ p4u144 Hãy cho đồng nghiệp của bạn điểm cao vì đã trở thành thiên tài! Cũng phát hiện ra! Thành thật mà nói tôi không biết liệu mã này có tôn trọng và tuân theo các liên kết tượng trưng hay không, nhưng nếu nó có một vòng lặp vô hạn. Bạn có thích thử nghiệm nó?
teedyay

8
@ p4u144 Không phải lo lắng về các liên kết tượng trưng. "Với các liên kết tượng trưng, ​​liên kết bị xóa và không phải là mục tiêu của liên kết." từ docs.oracle.com/javase/tutorial/essential/io/delete.html
corbin

3
Có một NPE có thể có ở đây: fileOrDirectory.listFiles()có thể trả về nullnếu có lỗi I / O khi đọc các tệp. Điều này được nêu rõ trong tài liệu: developer.android.com/reference/java/io/File.html#listFiles ()
Brian Yencho

67

Chúng ta có thể sử dụng các đối số dòng lệnh để xóa toàn bộ thư mục và nội dung của nó.

public static void deleteFiles(String path) {

    File file = new File(path);

    if (file.exists()) {
        String deleteCmd = "rm -r " + path;
        Runtime runtime = Runtime.getRuntime();
        try {
            runtime.exec(deleteCmd);
        } catch (IOException e) { }
    }
}

Ví dụ sử dụng mã trên:

deleteFiles("/sdcard/uploads/");

2
có vẻ tốt, bạn có biết điều này là đồng bộ hay không đồng bộ? Các tài liệu không nói: developer.android.com/reference/java/lang/
trộm

2
Ý kiến ​​tồi. Tại sao làm nó trên vỏ?
noamtm


32

Trong Kotlin, bạn có thể sử dụng deleteRecursively()tiện ích mở rộng từ kotlin.iogói

val someDir = File("/path/to/dir")
someDir.deleteRecursively()

2
Trong Java, bạn có thể sử dụng FilesKt.deleteRecursively(new File("/path/to/dir"));nếu bạn đang sử dụng kotlin-stdlib
Joonsoo

Lệnh này sẽ xóa thư mục "/ dir" với nội dung bên trong hoặc chỉ nội dung bên trong thư mục "/ dir" và thư mục vẫn còn đó ?.
Bhimbim

1
@Bhimbim hãy gửi tài liệu google cho bạn "Xóa tệp này với tất cả các con của nó.". Vì vậy, thư mục sẽ bị xóa cũng như nội dung
Dima Rostopira

Cảm ơn bạn @DimaRostopira!
Bhimbim

kotlin để giải cứu!
Tobi Oyelekan

15

sử dụng phương pháp dưới đây để xóa toàn bộ thư mục chính chứa các tệp và thư mục con của nó. Sau khi gọi phương thức này một lần nữa gọi thư mục xóa () của thư mục chính của bạn.

// For to Delete the directory inside list of files and inner Directory
public static boolean deleteDir(File dir) {
    if (dir.isDirectory()) {
        String[] children = dir.list();
        for (int i=0; i<children.length; i++) {
            boolean success = deleteDir(new File(dir, children[i]));
            if (!success) {
                return false;
            }
        }
    }

    // The directory is now empty so delete it
    return dir.delete();
}

Trong số tất cả các câu trả lời, đây là câu trả lời thực sự DUY NHẤT cũng xóa thư mục sau khi xóa các tệp trong đó.
zeeshan

Tệp tệp = Tệp mới (Môi trường.getExternalStorageDirectory () + separator + "folder_name" + separator); xóaDir (tập tin); Có cái này hoạt động. Cảm ơn :)
ashishdhiman2007

14

Cách tiếp cận của bạn là phù hợp cho một thư mục chỉ chứa các tệp, nhưng nếu bạn đang tìm kiếm một kịch bản cũng chứa các thư mục con thì cần phải đệ quy

Ngoài ra, bạn nên nắm bắt giá trị trả về của trả lại để đảm bảo bạn được phép xóa tệp

và bao gồm

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

trong bảng kê khai của bạn

void DeleteRecursive(File dir)
{
    Log.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
    if (dir.isDirectory())
    {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++)
        {
            File temp = new File(dir, children[i]);
            if (temp.isDirectory())
            {
                Log.d("DeleteRecursive", "Recursive Call" + temp.getPath());
                DeleteRecursive(temp);
            }
            else
            {
                Log.d("DeleteRecursive", "Delete File" + temp.getPath());
                boolean b = temp.delete();
                if (b == false)
                {
                    Log.d("DeleteRecursive", "DELETE FAIL");
                }
            }
        }

    }
    dir.delete();
}

5
Điều này có thể dễ dàng hơn nếu bạn sử dụng cho (File currentFile: file.listFiles ()) {
Thorben

8

Có rất nhiều câu trả lời, nhưng tôi quyết định thêm câu trả lời của riêng mình, vì nó hơi khác nhau. Nó dựa trên OOP;)

Tôi đã tạo lớp DirectoryCleaner , giúp tôi mỗi khi tôi cần dọn dẹp một số thư mục.

public class DirectoryCleaner {
    private final File mFile;

    public DirectoryCleaner(File file) {
        mFile = file;
    }

    public void clean() {
        if (null == mFile || !mFile.exists() || !mFile.isDirectory()) return;
        for (File file : mFile.listFiles()) {
            delete(file);
        }
    }

    private void delete(File file) {
        if (file.isDirectory()) {
            for (File child : file.listFiles()) {
                delete(child);
            }
        }
        file.delete();

    }
}

Nó có thể được sử dụng để giải quyết vấn đề này theo cách tiếp theo:

File dir = new File(Environment.getExternalStorageDirectory(), "your_directory_name");
new DirectoryCleaner(dir).clean();
dir.delete();

7

Nếu bạn không cần xóa mọi thứ một cách đệ quy, bạn có thể thử một cái gì đó như thế này:

File file = new File(context.getExternalFilesDir(null), "");
    if (file != null && file.isDirectory()) {
        File[] files = file.listFiles();
        if(files != null) {
            for(File f : files) {   
                f.delete();
            }
        }
    }

6

Bạn không thể xóa thư mục nếu nó có thư mục con hoặc tệp trong Java. Hãy thử giải pháp đơn giản hai dòng này. Điều này sẽ xóa thư mục và các cuộc thi bên trong thư mục.

File dirName = new File("directory path");
FileUtils.deleteDirectory(dirName);

Thêm dòng này trong tập tin lớp và đồng bộ hóa dự án

compile 'org.apache.commons:commons-io:1.3.2'  

Là một lớp lót 2, nó đơn giản. Nhưng việc cài đặt toàn bộ thư viện để sử dụng chỉ một trong những phương pháp của nó có vẻ không hiệu quả. Sử dụng cái này thay thế
Kathir

tip chèn gradle cứu cuộc sống của tôi.
Dracarys

5
public static void deleteDirectory( File dir )
{

    if ( dir.isDirectory() )
    {
        String [] children = dir.list();
        for ( int i = 0 ; i < children.length ; i ++ )
        {
         File child =    new File( dir , children[i] );
         if(child.isDirectory()){
             deleteDirectory( child );
             child.delete();
         }else{
             child.delete();

         }
        }
        dir.delete();
    }
}

5

xem android.os.FileUtils, nó ẩn trên API 21

public static boolean deleteContents(File dir) {
    File[] files = dir.listFiles();
    boolean success = true;
    if (files != null) {
        for (File file : files) {
            if (file.isDirectory()) {
                success &= deleteContents(file);
            }
            if (!file.delete()) {
                Log.w("Failed to delete " + file);
                success = false;
            }
        }
    }
    return success;
}

Nguồn: https://android.googlesource.com/pl platform / frameworks / base / + / master / core / java / android / os / FileUtils.java # 414


4

Theo tài liệu :

Nếu tên đường dẫn trừu tượng này không biểu thị một thư mục, thì phương thức này trả về null.

Vì vậy, bạn nên kiểm tra nếu listFilesnullvà chỉ tiếp tục nếu không

boolean deleteDirectory(File path) {
    if(path.exists()) {
        File[] files = path.listFiles();
        if (files == null) {
            return false;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                deleteDirectory(file);
            } else {
                boolean wasSuccessful = file.delete();
                if (wasSuccessful) {
                    Log.i("Deleted ", "successfully");
                }
            }
        }
    }
    return(path.delete());
}

1
Đây phải là câu trả lời được chấp nhận. Hoạt động như một lá bùa!
MSeiz5

3

Đây là những gì tôi làm ... (ngắn gọn và đã thử nghiệm)

    ...
    deleteDir(new File(dir_to_be_deleted));
    ...

    // delete directory and contents
    void deleteDir(File file) { 
        if (file.isDirectory())
            for (String child : file.list())
                deleteDir(new File(file, child));
        file.delete();  // delete child file or empty directory
    }

3
private static void deleteRecursive(File dir)
{
    //Log.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
    if (dir.isDirectory())
    {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++)
        {
            File temp = new File(dir, children[i]);
            deleteRecursive(temp);
        }

    }

    if (dir.delete() == false)
    {
        Log.d("DeleteRecursive", "DELETE FAIL");
    }
}

2

Cách đơn giản để xóa tất cả các tập tin từ thư mục:

Đây là chức năng chung để xóa tất cả hình ảnh khỏi thư mục bằng cách chỉ gọi

xóa AllImageFile (bối cảnh);

public static void deleteAllFile(Context context) {
File directory = context.getExternalFilesDir(null);
        if (directory.isDirectory()) {
            for (String fileName: file.list()) {
                new File(file,fileName).delete();
            }
        }    
    } 

2

Mã an toàn nhất mà tôi biết:

private boolean recursiveRemove(File file) {
    if(file == null  || !file.exists()) {
        return false;
    }

    if(file.isDirectory()) {
        File[] list = file.listFiles();

        if(list != null) {

            for(File item : list) {
                recursiveRemove(item);
            }

        }
    }

    if(file.exists()) {
        file.delete();
    }

    return !file.exists();
}

Kiểm tra tệp tồn tại, xử lý null, kiểm tra thư mục đã thực sự bị xóa


1

Đây là một triển khai không đệ quy, chỉ để cho vui:

/**
 * Deletes the given folder and all its files / subfolders.
 * Is not implemented in a recursive way. The "Recursively" in the name stems from the filesystem command
 * @param root The folder to delete recursively
 */
public static void deleteRecursively(final File root) {
    LinkedList<File> deletionQueue = new LinkedList<>();
    deletionQueue.add(root);

    while(!deletionQueue.isEmpty()) {
        final File toDelete = deletionQueue.removeFirst();
        final File[] children = toDelete.listFiles();
        if(children == null || children.length == 0) {
            // This is either a file or an empty directory -> deletion possible
            toDelete.delete();
        } else {
            // Add the children before the folder because they have to be deleted first
            deletionQueue.addAll(Arrays.asList(children));
            // Add the folder again because we can't delete it yet.
            deletionQueue.addLast(toDelete);
        }
    }
}

1

Phiên bản koltin ngắn

fun File.deleteDirectory(): Boolean {
    return if (exists()) {
        listFiles()?.forEach {
            if (it.isDirectory) {
                it.deleteDirectory()
            } else {
                it.delete()
            }
        }
        delete()
    } else false
}

1

Điều này (Cố gắng xóa tất cả các tệp phụ và thư mục con bao gồm thư mục được cung cấp) :

  1. Nếu File, xóa
  2. Nếu Empty Directory, xóa
  3. nếu Not Empty Directory, gọi xóa một lần nữa với thư mục con, lặp lại 1 đến 3

thí dụ:

File externalDir = Environment.getExternalStorageDirectory()
Utils.deleteAll(externalDir); //BE CAREFUL.. Will try and delete ALL external storage files and directories

Để có quyền truy cập vào Thư mục lưu trữ ngoài, bạn cần có các quyền sau:

(Sử dụng ContextCompat.checkSelfPermissionActivityCompat.requestPermissions)

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Phương pháp đệ quy:

public static boolean deleteAll(File file) {
    if (file == null || !file.exists()) return false;

    boolean success = true;
    if (file.isDirectory()) {
        File[] files = file.listFiles();
        if (files != null && files.length > 0) {
            for (File f : files) {
                if (f.isDirectory()) {
                    success &= deleteAll(f);
                }
                if (!f.delete()) {
                    Log.w("deleteAll", "Failed to delete " + f);
                    success = false;
                }
            }
        } else {
            if (!file.delete()) {
                Log.w("deleteAll", "Failed to delete " + file);
                success = false;
            }
        }
    } else {
        if (!file.delete()) {
            Log.w("deleteAll", "Failed to delete " + file);
            success = false;
        }
    }
    return success;
}

0

Tôi đã đặt cái này mặc dù các bước của nó sẽ xóa một thư mục với bất kỳ cấu trúc thư mục nào.

public int removeDirectory(final File folder) {

    if(folder.isDirectory() == true) {
        File[] folderContents = folder.listFiles();
        int deletedFiles = 0;

        if(folderContents.length == 0) {
            if(folder.delete()) {
                deletedFiles++;
                return deletedFiles;
            }
        }
        else if(folderContents.length > 0) {

            do {

                File lastFolder = folder;
                File[] lastFolderContents = lastFolder.listFiles();

                //This while loop finds the deepest path that does not contain any other folders
                do {

                    for(File file : lastFolderContents) {

                        if(file.isDirectory()) {
                            lastFolder = file;
                            lastFolderContents = file.listFiles();
                            break;
                        }
                        else {

                            if(file.delete()) {
                                deletedFiles++;
                            }
                            else {
                                break;
                            }

                        }//End if(file.isDirectory())

                    }//End for(File file : folderContents)

                } while(lastFolder.delete() == false);

                deletedFiles++;
                if(folder.exists() == false) {return deletedFiles;}

            } while(folder.exists());
        }
    }
    else {
        return -1;
    }

    return 0;

}

Hi vọng điêu nay co ich.


0
//To delete all the files of a specific folder & subfolder
public static void deleteFiles(File directory, Context c) {
    try {
        for (File file : directory.listFiles()) {
            if (file.isFile()) {
                final ContentResolver contentResolver = c.getContentResolver();
                String canonicalPath;
                try {
                    canonicalPath = file.getCanonicalPath();
                } catch (IOException e) {
                    canonicalPath = file.getAbsolutePath();
                }
                final Uri uri = MediaStore.Files.getContentUri("external");
                final int result = contentResolver.delete(uri,
                        MediaStore.Files.FileColumns.DATA + "=?", new String[]{canonicalPath});
                if (result == 0) {
                    final String absolutePath = file.getAbsolutePath();
                    if (!absolutePath.equals(canonicalPath)) {
                        contentResolver.delete(uri,
                                MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
                    }
                }
                if (file.exists()) {
                    file.delete();
                    if (file.exists()) {
                        try {
                            file.getCanonicalFile().delete();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (file.exists()) {
                            c.deleteFile(file.getName());
                        }
                    }
                }
            } else
                deleteFiles(file, c);
        }
    } catch (Exception e) {
    }
}

Đây là giải pháp của bạn, nó cũng sẽ làm mới bộ sưu tập.


0

Một cách khác (hiện đại) để giải quyết nó.

public class FileUtils {
    public static void delete(File fileOrDirectory) {
        if(fileOrDirectory != null && fileOrDirectory.exists()) {
            if(fileOrDirectory.isDirectory() && fileOrDirectory.listFiles() != null) {      
                Arrays.stream(fileOrDirectory.listFiles())
                      .forEach(FileUtils::delete);
            }
            fileOrDirectory.delete();
        }
    }
}

Trên Android kể từ API 26

public class FileUtils {

    public static void delete(File fileOrDirectory)  {
        if(fileOrDirectory != null) {
            delete(fileOrDirectory.toPath());
        }
    }

    public static void delete(Path path)  {
        try {
            if(Files.exists(path)) {
                Files.walk(path)
                        .sorted(Comparator.reverseOrder())
                        .map(Path::toFile)
//                      .peek(System.out::println)
                        .forEach(File::delete);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
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.