ChatGPT解决这个技术问题 Extra ChatGPT

如何删除整个文件夹和内容?

我希望我的应用程序的用户能够删除 DCIM 文件夹(位于 SD 卡上并包含子文件夹)。

这可能吗,如果可以,怎么办?

除了递归自下而上删除方法?
如果您有一个非常大或复杂的目录,您应该使用 rm -rf directory 而不是 FileUtils.deleteDirectory。在进行基准测试后,我们发现它快了好几倍。在此处查看示例实现:stackoverflow.com/a/58421350/293280

t
teedyay

您可以像这样递归地删除文件和文件夹:

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

    fileOrDirectory.delete();
}

我没有做过效率测试,但我相信我的更强大。 chirag 将适用于 DCIM 文件夹的特定情况,其中 DCIM 中的文件夹应仅包含文件(即 DCIM 中的文件夹通常不包含任何子文件夹)。我的版本将删除嵌套到任何深度的文件夹。用户有可能修改了他的 SD 卡的内容,以便 DCIM 包含嵌套更深的文件夹(例如 DCIM\foo\bar\pic.jpg),在这种情况下 chirag 的代码将失败。
一个同事问我的一个问题:如果一个文件夹本身有一个符号链接并且你执行这段代码会发生什么?
@p4u144 给你的同事高五分!好眼力!老实说,我不知道这段代码是否会尊重并遵循符号链接,但如果是的话,你将有一个无限循环。你喜欢测试它吗?
@p4u144 不用担心符号链接。 “使用符号链接,链接被删除,而不是链接的目标。”来自docs.oracle.com/javase/tutorial/essential/io/delete.html
这里可能存在 NPE:如果在读取文件时出现 I/O 错误,fileOrDirectory.listFiles() 可能会返回 null。这在文档中明确说明:developer.android.com/reference/java/io/File.html#listFiles()
C
Community

首先让我告诉你,你不能删除 DCIM 文件夹,因为它是一个系统文件夹。当您在手机上手动删除它时,它将删除该文件夹的内容,但不会删除 DCIM 文件夹。您可以使用以下方法删除其内容:

根据评论更新

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

erm 我如何声明 dir 是什么?
您必须使用 dicm 文件夹的路径声明目录:使用文件 r=file(path);
使用的文件目录=新文件(Environment.getExternalStorageDirectory()+“/DCIM/100MEDIA”);
@chiragshah 在删除文件夹并重新创建文件夹后,导致创建一个与提到的文件夹同名的未知文件。如果我试图访问该文件,它会抛出异常,如资源或设备忙。我还检查了属性我在其中找到 MD5 签名的文件:操作失败
文件夹必须存在于存储中。如果没有,我们可以再检查一个代码来检查这个。 if (myDir.exists() && myDir.isDirectory())
M
Mapsy

我们可以使用命令行参数来删除整个文件夹及其内容。

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

上述代码的示例用法:

deleteFiles("/sdcard/uploads/");

看起来不错,你知道这是同步的还是异步的?文档没有说:developer.android.com/reference/java/lang/…
馊主意。为什么要在外壳上做?
如果文件名有空格,则不起作用。例如“/storage/emulated/0/Test create/test test/”。任何想法。请帮忙
D
Dima Rostopira

在 Kotlin 中,您可以使用 kotlin.io 包中的 deleteRecursively() 扩展

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

在 Java 中,如果您使用的是 kotlin-stdlib,则可以使用 FilesKt.deleteRecursively(new File("/path/to/dir"));
此命令将删除包含内容的“/dir”目录或仅删除“/dir”目录中的内容,并且该目录仍然存在?
@Bhimbim lemme google docs for you“删除此文件及其所有子文件。”。因此,目录和内容都将被删除
kotlin 来救援!
我刚刚使用它,它似乎有效,我相信如果你只使用 dir.delete() 并且文件夹中有内容,它不会删除它,但如果你有内容,这可以完成工作
V
Vlad

简短的 koltin 版本

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

更新

Kotlin 标准库函数

file.deleteRecursively()

A
Android

使用以下方法删除包含文件的整个主目录及其子目录。再次调用此方法后,调用主目录的 delete() 目录。

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

在所有答案中,这是在删除目录中的文件后也删除目录的唯一真正答案。
文件文件 = 新文件(Environment.getExternalStorageDirectory() + 分隔符 + “文件夹名称” + 分隔符); deleteDir(file); 是的,这行得通。谢谢 :)
S
Sri Harsha Chilakapati

您的方法对于仅包含文件的文件夹来说是不错的,但如果您正在寻找还包含子文件夹的场景,则需要递归

此外,您应该捕获返回的返回值,以确保您被允许删除文件

并包括

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

在你的清单中

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

如果您使用 for (File currentFile : file.listFiles()) {
g
gio

有很多答案,但我决定添加我自己的,因为它有点不同。它基于 OOP ;)

我创建了 DirectoryCleaner 类,每当我需要清理某个目录时,它都会帮助我。

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

    }
}

它可用于通过以下方式解决此问题:

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

s
starbeamrainbowlabs

如果该目录在 Java 中有子目录或文件,则不能删除该目录。试试这个两行简单的解决方案。这将删除目录和目录内的比赛。

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

在 gradle 文件中添加这一行并同步项目

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

作为 2 班轮,这很简单。但是安装整个库以仅使用其中一种方法似乎效率低下。请改用 this
gradle 插入提示救了我的命。
H
HB.

根据documentation

如果此抽象路径名不表示目录,则此方法返回 null。

因此,您应该检查 listFiles 是否为 null,只有在不是时才继续

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

这应该是公认的答案。奇迹般有效!
M
Marty

如果你不需要递归删除东西,你可以尝试这样的事情:

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

D
Deep Verma
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();
    }
}

J
Jared Burrows

请参阅 android.os.FileUtils,它隐藏在 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;
}

来源:https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/FileUtils.java#414


M
Master

最快最简单的方法:

public static boolean deleteFolder(File removableFolder) {
        File[] files = removableFolder.listFiles();
        if (files != null && files.length > 0) {
            for (File file : files) {
                boolean success;
                if (file.isDirectory())
                    success = deleteFolder(file);
                else success = file.delete();
                if (!success) return false;
            }
        }
        return removableFolder.delete();
}

S
SoloPilot

这就是我所做的......(简洁且经过测试)

    ...
    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
    }

J
Jared Burrows
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");
    }
}

S
Sagar Chorage

从目录中删除所有文件的简单方法:

它是通过仅调用从目录中删除所有图像的通用功能

删除所有图像文件(上下文);

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

G
Gary Davies

我知道的最安全的代码:

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

检查文件是否存在,处理空值,检查目录是否被实际删除


B
Bilal Mustafa
//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) {
    }
}

这是您的解决方案,它也将刷新图库。


P
PhilLab

这是一个非递归实现,只是为了好玩:

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

解决方案还不错,但命名有点误导。
P
Pierre

这(尝试删除所有子文件和子目录,包括提供的目录):

If File, delete If Empty Directory, delete if Not Empty Directory, 再用子目录调用delete, 重复1到3

例子:

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

要访问外部存储目录,您需要以下权限:

(使用 ContextCompat.checkSelfPermissionActivityCompat.requestPermissions

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

递归方法:

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

u
user2288580

我已经放了这个,尽管它会删除具有任何目录结构的文件夹。

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;

}

希望这可以帮助。


C
Ch4rl3x

解决它的另一种(现代)方法。

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

自 API 26 起在 Android 上

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

Z
Z3R0

我正在使用这个递归函数来完成这项工作:

public static void deleteDirAndContents(@NonNull File mFile){
    if (mFile.isDirectory() && mFile.listFiles() != null && mFile.listFiles().length > 0x0) {
        for (File file : mFile.listFiles()) {
            deleteDirAndContents(file);
        }
    } else {
        mFile.delete();
    }
}

该函数检查它是目录还是文件。

如果它是一个目录检查它是否有子文件,如果它有子文件将再次调用自己传递孩子并重复。

如果它是一个文件,它会删除它。

(不要使用此功能通过传递缓存目录来清除应用程序缓存,因为它也会删除缓存目录,因此应用程序将崩溃...如果要清除缓存,请使用此功能,不会删除你传递给它的目录:

public static void deleteDirContents(@NonNull File mFile){
        if (mFile.isDirectory() && mFile.listFiles() != null && mFile.listFiles().length > 0x0) {
            for (File file : mFile.listFiles()) {
                deleteDirAndContents(file);
            }
        }
    }

或者您可以使用以下命令检查它是否是缓存目录:

if (!mFile.getAbsolutePath().equals(context.getCacheDir().getAbsolutePath())) {
    mFile.delete();
}

清除应用缓存的示例代码:

public static void clearAppCache(Context context){
        try {
            File cache = context.getCacheDir();
            FilesUtils.deleteDirContents(cache);
        } catch (Exception e){
            MyLogger.onException(TAG, e);
        }
    }

再见,祝你有美好的一天和编码:D