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

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


当前回答

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

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

其他回答

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

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

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

如果是文件,删除 如果是空目录,请删除 如果不是空目录,再次调用删除子目录,重复1到3

例子:

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

访问“外部存储目录”需要具备以下权限:

(使用ContextCompat。checkSelfPermission和ActivityCompat.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;
}

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

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

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

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

    fileOrDirectory.delete();
}

这是另一种(现代)解决方法。

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