【问题标题】:How to delete a whole folder and content?如何删除整个文件夹和内容?
【发布时间】:2011-06-24 00:55:16
【问题描述】:

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

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

【问题讨论】:

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

标签: android file-io directory delete-directory


【解决方案1】:

最快最简单的方法:

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

【讨论】:

    【解决方案2】:

    简短的 koltin 版本

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

    更新

    Kotlin 标准库函数

    file.deleteRecursively()
    

    【讨论】:

      【解决方案3】:

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

      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

      【讨论】:

        【解决方案4】:

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

        1. 如果File,删除
        2. 如果Empty Directory,删除
        3. 如果Not Empty Directory,再次调用删除子目录,重复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;
        }
        

        【讨论】:

          【解决方案5】:

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

          【讨论】:

          • 这应该是公认的答案。像魅力一样工作!
          【解决方案6】:

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

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

          【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:
            //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) {
                }
            }
            

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

            【讨论】:

              【解决方案9】:

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

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

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

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

              【讨论】:

              • 作为 2 班轮,很简单。但是安装整个库以仅使用其中一种方法似乎效率低下。请改用this
              • gradle 插入提示救了我的命。
              【解决方案10】:

              在 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() 并且文件夹中有内容,它不会删除它,但这样可以以防万一你里面有内容
              【解决方案11】:

              我知道的最安全的代码:

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

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

              【讨论】:

                【解决方案12】:

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

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

                希望这会有所帮助。

                【讨论】:

                  【解决方案13】:

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

                  只调用即可删除目录中所有图片的通用函数

                  deleteAllImageFile(context);

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

                  【讨论】:

                    【解决方案14】:

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

                    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()
                    【解决方案15】:

                    查看 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

                    【讨论】:

                      【解决方案16】:
                      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");
                          }
                      }
                      

                      【讨论】:

                        【解决方案17】:

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

                        更新根据 cmets

                        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);
                        • 使用的文件目录 = new File(Environment.getExternalStorageDirectory()+"/DCIM/100MEDIA");
                        • @chiragshah 在删除文件夹并重新创建文件夹后,会创建一个与提到的文件夹同名的未知文件。如果我试图访问该文件,则会抛出类似 的异常资源或设备繁忙。我还检查了我发现 MD5 Signature:Operation Failure 的文件属性
                        • 文件夹必须存在于存储中。如果没有,我们可以再检查一个代码来检查这个。 if (myDir.exists() && myDir.isDirectory())
                        【解决方案18】:

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

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

                        【讨论】:

                          【解决方案19】:

                          有很多答案,但我决定添加我自己的,因为它有点不同。它基于 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();
                          

                          【讨论】:

                            【解决方案20】:

                            使用以下方法删除包含文件的整个主目录及其子目录。再次调用此方法后,调用主目录的 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();
                            }
                            

                            【讨论】:

                            • 在所有答案中,这是唯一真正的答案,它在删除目录后也删除了其中的文件。
                            • 文件 file = new File(Environment.getExternalStorageDirectory() + separator + "folder_name" + separator); deleteDir(file); 是的,这行得通。谢谢:)
                            【解决方案21】:

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

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

                            【讨论】:

                              【解决方案22】:

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

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

                              并包含

                              <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()) { 这可能会更容易
                              【解决方案23】:
                              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();
                                  }
                              }
                              

                              【讨论】:

                                【解决方案24】:

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

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

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 2010-09-16
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多