Как удалить папку с файлами с помощью Java

104

Я хочу создать и удалить каталог с помощью Java, но он не работает.

File index = new File("/home/Work/Indexer1");
if (!index.exists()) {
    index.mkdir();
} else {
    index.delete();
    if (!index.exists()) {
        index.mkdir();
    }
}
Мистер Дж.
источник
3
Что случилось, когда вы попробовали?
Абимаран Кугатасан
В чем вопрос?
Aniket Thakur
1
индексный файл не удалить.
Mr.G
1
См. Как удалить каталог на Java
Аникет Тхакур,
1
К сожалению, @AniketThakur, этот подход будет следовать символическим ссылкам и удалять файлы и каталоги, которые, возможно, не были предназначены.
Хэнк Шульц

Ответы:

99

Java не может удалять папки с данными. Перед удалением папки необходимо удалить все файлы.

Используйте что-то вроде:

String[]entries = index.list();
for(String s: entries){
    File currentFile = new File(index.getPath(),s);
    currentFile.delete();
}

Тогда вы сможете удалить папку с помощью index.delete() Untested!

Cemron
источник
37
Это не приведет к удалению непустых подкаталогов.
Франческо Мензани,
13
вы должны написать рекурсивный метод или использовать, FileUtils.deleteDirectoryкак сказал @Francesco Menzani.
EN20,
4
Будь очень осторожен. Если index является символической ссылкой на другой каталог, вы закончите удаление содержимого другого каталога. К сожалению, я еще не нашел хорошего способа обнаружения символических ссылок в Windows в Java 6, хотя Java 7 предоставляет Files.isSymbolicLink ().
Хэнк Шульц
1
Решение: оберните этот фрагмент кода в if (!index.delete()) {...}. Затем, если index является символической ссылкой, она удаляется независимо от того, есть ли у нее содержимое.
Хэнк Шульц
Это вызовет исключение NullPointerException, если при чтении каталога возникнет исключение ввода-вывода. Код должен проверить, entriesявляется ли он нулевым.
Мернст
178

Просто однострочник.

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

Документация здесь

Барри Кнапп
источник
обновленная ссылка: commons.apache.org/proper/commons-io/javadocs/api-2.5/org/…
OhadR 07
13
эм ... нет. Это однострочный файл с внешней зависимостью, о чем важно помнить. Такая простая внешняя зависимость используется только тогда, когда вы занимаетесь личным домашним проектом или ваша компания действительно не заботится о возможности получить иск.
searchchengine27 05
11
@ searchchengine27, но кажется, что библиотека находится в Apache Commons, поэтому риск предъявления иска незначителен. whitesourcesoftware.com/whitesource-blog/… .
simtim
1
@simtim, вы полностью упускаете из виду. Компания никогда не одобрит библиотеку для использования без команды юристов, которые сначала ознакомят с условиями использования, соглашениями с конечным пользователем и любыми другими юридическими документами, связанными с библиотекой. Кто-то должен платить этим юристам ... иногда никто не хочет, а это означает, что разработчик не может этим пользоваться. Чем крупнее компания, в которой вы работаете, тем больше волокиты вам придется пройти.
searchchengine27
19
@ searchchengine27 нет, вы полностью упускаете суть. Компания, которой нужна армия юристов, чтобы разрешить использование Apache Commons, является абсолютной патологией и совсем не нормой в мире ИТ. Я никогда не слышал, чтобы у кого-то были такие проблемы, и если у вас есть такие проблемы, у вас, скорее всего, доступ к SO заблокирован, поэтому ответ все равно не будет вам доступен.
9ilsdx 9rvj 0lo
94

Это работает, и хотя пропуск проверки каталога выглядит неэффективным, это не так: проверка выполняется сразу в listFiles().

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            deleteDir(f);
        }
    }
    file.delete();
}

Обновите, чтобы избежать следующих символических ссылок:

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            if (! Files.isSymbolicLink(f.toPath())) {
                deleteDir(f);
            }
        }
    }
    file.delete();
}
Джефф Лирман
источник
2
Как оказалось, в этом есть ошибка. Если другой процесс удаляет файлы во время цикла, это может вызвать исключение, которое следует перехватить и проигнорировать.
Джефф Лирман 08
2
@ 9ilsdx9rvj0lo Вместо того, чтобы быть язвительным, вы могли бы внести правку для обработки символических ссылок. ОП ничего не сказал о символических ссылках в своем сообщении. Просто создание и удаление каталога. Также укажите, что «многого не хватает». Помогите нам.
Perry Tew
@PerryTew Я не дури. Я просто указываю, что я полностью не согласен с вашим комментарием о том, что ответ лучше, потому что внешние библиотеки не используются. Это не. Есть веская причина, по которой люди используют apache commons: вам не нужно ничего программировать самостоятельно. Символические ссылки - это всего лишь пример того, что вам будет не хватать при написании всего с нуля.
9ilsdx 9rvj 0lo
2
Дело не в том, что лучше / хуже, а в плюсах и минусах. Отсутствие зависимости от внешних библиотек иногда является значительным преимуществом. Конечно, использование проверенного программного обеспечения дает значительные преимущества. Разработчик должен уравновесить проблемы. Если есть ошибки, кроме двух уже упомянутых, мы обязательно хотели бы знать о них.
Джефф Лирман
31

Я предпочитаю это решение на java 8:

  Files.walk(pathToBeDeleted)
    .sorted(Comparator.reverseOrder())
    .map(Path::toFile)
    .forEach(File::delete);

С этого сайта: http://www.baeldung.com/java-delete-directory

нирмал
источник
2
Обратите внимание, что при этом могут возникнуть проблемы с масштабируемостью, поскольку он строит полный список, создает отсортированную копию, а затем выполняет итерацию по отсортированной копии. В старые добрые времена, когда память не была неисчерпаемой, это было бы очень плохой идеей. Это кратко, но с ценой в пространстве (O (N) против O (1)) и эффективности (O (N log N) против O (N)). В большинстве случаев это не имеет значения.
Джефф Лирман
Я должен был сказать «пробел O (N) против O (глубина)» выше, где глубина - это глубина дерева каталогов (сравнивая это решение с рекурсивными решениями).
Джефф Лирман 02
1
это элегантно, работает и не полагается на внешние библиотеки. любил это
Лео
Разве это не проблема утечки дескрипторов файлов? В этом примере поток, возвращаемый с помощью , не закрывается Files.walk(), что явно указано в документации API. Я знаю, что если вы, например, не закроете поток, возвращенный, Files.list()у вас могут закончиться ручки, и программа выйдет из строя. См., Например, stackoverflow.com/q/36990053/421049 и stackoverflow.com/q/26997240/421049 .
Гаррет Уилсон
24

В JDK 7 вы можете использовать Files.walkFileTree()и Files.deleteIfExists()для удаления дерева файлов. (Пример: http://fahdshariff.blogspot.ru/2011/08/java-7-deleting-directory-by-walking.html )

В JDK 6 один из возможных способов - использовать FileUtils.deleteQuietly из Apache Commons, который удалит файл, каталог или каталог с файлами и подкаталогами.

Андрей Чащев
источник
6
Вот пример: fahdshariff.blogspot.ru/2011/08/…
Андрей
23

Используя Apache Commons-IO, он выглядит следующим образом:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

Это (немного) более производительно, чем FileUtils.deleteDirectory.

JRA_TLL
источник
группа: 'commons-io', имя: 'commons-io', версия: '2. +' - полезно
mike rodent
10

Как уже упоминалось, Java не может удалить папку, содержащую файлы, поэтому сначала удалите файлы, а затем папку.

Вот простой пример:

import org.apache.commons.io.FileUtils;



// First, remove files from into the folder 
FileUtils.cleanDirectory(folder/path);

// Then, remove the folder
FileUtils.deleteDirectory(folder/path);

Или:

FileUtils.forceDelete(new File(destination));
Гавриэль Коэн
источник
9

Моя базовая рекурсивная версия, работающая со старыми версиями JDK:

public static void deleteFile(File element) {
    if (element.isDirectory()) {
        for (File sub : element.listFiles()) {
            deleteFile(sub);
        }
    }
    element.delete();
}
Пьер Леме
источник
2
Это вызовет исключение NullPointerException, если при чтении каталога возникнет исключение ввода-вывода. Код должен проверять, listFiles()возвращает ли значение null, а не вызывать isDirectory().
Мернст
9

Это лучшее решение для Java 7+:

public static void deleteDirectory(String directoryFilePath) throws IOException
{
    Path directory = Paths.get(directoryFilePath);

    if (Files.exists(directory))
    {
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>()
        {
            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException
            {
                Files.delete(path);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path directory, IOException ioException) throws IOException
            {
                Files.delete(directory);
                return FileVisitResult.CONTINUE;
            }
        });
    }
}
BullyWiiPlaza
источник
6

Guava 21+ спешит на помощь. Используйте только в том случае, если нет символических ссылок, указывающих на каталог, который нужно удалить.

com.google.common.io.MoreFiles.deleteRecursively(
      file.toPath(),
      RecursiveDeleteOption.ALLOW_INSECURE
) ;

(Этот вопрос хорошо проиндексирован Google, поэтому другие люди, использующие Гуава, могут быть счастливы найти этот ответ, даже если он повторяется с другими ответами в другом месте.)

Лоран Кайетт
источник
4

Мне больше всего нравится это решение. Он не использует стороннюю библиотеку, вместо этого он использует NIO2 из Java 7.

/**
 * Deletes Folder with all of its content
 *
 * @param folder path to folder which should be deleted
 */
public static void deleteFolderAndItsContent(final Path folder) throws IOException {
    Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            if (exc != null) {
                throw exc;
            }
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}
Javo
источник
3

Еще один вариант - использовать org.springframework.util.FileSystemUtilsсоответствующий метод Spring, который рекурсивно удалит все содержимое каталога.

File directoryToDelete = new File(<your_directory_path_to_delete>);
FileSystemUtils.deleteRecursively(directoryToDelete);

Это сработает!

dZ.
источник
2

В этом

index.delete();

            if (!index.exists())
               {
                   index.mkdir();
               }

ты звонишь

 if (!index.exists())
                   {
                       index.mkdir();
                   }

после

index.delete();

Это означает, что вы снова создаете файл после удаления File.delete () возвращает логическое значение. Итак, если вы хотите проверить, сделайте это, System.out.println(index.delete());если вы получите, trueтогда это означает, что файл удален

File index = new File("/home/Work/Indexer1");
    if (!index.exists())
       {
             index.mkdir();
       }
    else{
            System.out.println(index.delete());//If you get true then file is deleted




            if (!index.exists())
               {
                   index.mkdir();// here you are creating again after deleting the file
               }




        }

из комментариев, приведенных ниже, обновленный ответ выглядит следующим образом

File f=new File("full_path");//full path like c:/home/ri
    if(f.exists())
    {
        f.delete();
    }
    else
    {
        try {
            //f.createNewFile();//this will create a file
            f.mkdir();//this create a folder
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
SpringLearner
источник
2

Если у вас есть подпапки, у вас возникнут проблемы с ответами Cemron. поэтому вы должны создать метод, который работает следующим образом:

private void deleteTempFile(File tempFile) {
        try
        {
            if(tempFile.isDirectory()){
               File[] entries = tempFile.listFiles();
               for(File currentFile: entries){
                   deleteTempFile(currentFile);
               }
               tempFile.delete();
            }else{
               tempFile.delete();
            }
        getLogger().info("DELETED Temporal File: " + tempFile.getPath());
        }
        catch(Throwable t)
        {
            getLogger().error("Could not DELETE file: " + tempFile.getPath(), t);
        }
    }
Пантро
источник
2

Вы можете использовать FileUtils.deleteDirectory . JAVA не может удалить непустые складки с помощью File.delete () .

Иссам Рессани
источник
1

directry не может просто удалить, если в нем есть файлы, поэтому вам может потребоваться сначала удалить файлы внутри, а затем каталог

public class DeleteFileFolder {

public DeleteFileFolder(String path) {

    File file = new File(path);
    if(file.exists())
    {
        do{
            delete(file);
        }while(file.exists());
    }else
    {
        System.out.println("File or Folder not found : "+path);
    }

}
private void delete(File file)
{
    if(file.isDirectory())
    {
        String fileList[] = file.list();
        if(fileList.length == 0)
        {
            System.out.println("Deleting Directory : "+file.getPath());
            file.delete();
        }else
        {
            int size = fileList.length;
            for(int i = 0 ; i < size ; i++)
            {
                String fileName = fileList[i];
                System.out.println("File path : "+file.getPath()+" and name :"+fileName);
                String fullPath = file.getPath()+"/"+fileName;
                File fileOrFolder = new File(fullPath);
                System.out.println("Full Path :"+fileOrFolder.getPath());
                delete(fileOrFolder);
            }
        }
    }else
    {
        System.out.println("Deleting file : "+file.getPath());
        file.delete();
    }
}
Индранил.Бхарамбе
источник
1

Вы можете сделать рекурсивный вызов, если существуют подкаталоги

import java.io.File;

class DeleteDir {
public static void main(String args[]) {
deleteDirectory(new File(args[0]));
}

static public boolean deleteDirectory(File path) {
if( path.exists() ) {
  File[] files = path.listFiles();
  for(int i=0; i<files.length; i++) {
     if(files[i].isDirectory()) {
       deleteDirectory(files[i]);
     }
     else {
       files[i].delete();
     }
  }
}
return( path.delete() );
}
}
prem30488
источник
1

мы можем использовать spring-coreзависимость;

boolean result = FileSystemUtils.deleteRecursively(file);
Канагавелу Сугумар
источник
1

Большинство ответов (даже недавних), ссылающихся на классы JDK, полагаются на, File.delete()но это ошибочный API, поскольку операция может завершиться с ошибкой.
В java.io.File.delete()документации метода указано:

Обратите внимание, что java.nio.file.Filesкласс определяет deleteметод, который IOExceptionбудет выдавать, когда файл не может быть удален. Это полезно для отчетов об ошибках и для диагностики, почему файл не может быть удален.

В качестве замены вы должны отдать предпочтение Files.delete(Path p) тому, чтобыIOException сообщение об ошибке.

Фактический код можно было бы написать так:

Path index = Paths.get("/home/Work/Indexer1");

if (!Files.exists(index)) {
    index = Files.createDirectories(index);
} else {

    Files.walk(index)
         .sorted(Comparator.reverseOrder())  // as the file tree is traversed depth-first and that deleted dirs have to be empty  
         .forEach(t -> {
             try {
                 Files.delete(t);
             } catch (IOException e) {
                 // LOG the exception and potentially stop the processing

             }
         });
    if (!Files.exists(index)) {
        index = Files.createDirectories(index);
    }
}
davidxxx
источник
0

вы можете попробовать следующее

  File dir = new File("path");
   if (dir.isDirectory())
   {
         dir.delete();
   }

Если внутри вашей папки есть подпапки, вам может потребоваться рекурсивно удалить их.

Ручира Гаян Ранавира
источник
0
private void deleteFileOrFolder(File file){
    try {
        for (File f : file.listFiles()) {
            f.delete();
            deleteFileOrFolder(f);
        }
    } catch (Exception e) {
        e.printStackTrace(System.err);
    }
}
Марсело Лопес
источник
0
        import org.apache.commons.io.FileUtils;

        List<String> directory =  new ArrayList(); 
        directory.add("test-output"); 
        directory.add("Reports/executions"); 
        directory.add("Reports/index.html"); 
        directory.add("Reports/report.properties"); 
        for(int count = 0 ; count < directory.size() ; count ++)
        {
        String destination = directory.get(count);
        deleteDirectory(destination);
        }





      public void deleteDirectory(String path) {

        File file  = new File(path);
        if(file.isDirectory()){
             System.out.println("Deleting Directory :" + path);
            try {
                FileUtils.deleteDirectory(new File(path)); //deletes the whole folder
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        else {
        System.out.println("Deleting File :" + path);
            //it is a simple file. Proceed for deletion
            file.delete();
        }

    }

Работает как шарм. И для папки, и для файлов. Салам :)

Муштак Ахмед
источник
-1

Удалите это из другой части

File index = new File("/home/Work/Indexer1");
if (!index.exists())
{
     index.mkdir();
     System.out.println("Dir Not present. Creating new one!");
}
index.delete();
System.out.println("File deleted successfully");
Аникет Такур
источник
-1

Некоторые из этих ответов кажутся излишне длинными:

if (directory.exists()) {
    for (File file : directory.listFiles()) {
        file.delete();
    }
    directory.delete();
}

Также работает для подкаталогов.

Адам Шорт
источник
-3

Вы можете использовать эту функцию

public void delete()    
{   
    File f = new File("E://implementation1/");
    File[] files = f.listFiles();
    for (File file : files) {
        file.delete();
    }
}
Пиюш Румао
источник
Прекрасно работает с каталогом со всеми закрытыми файлами. Но при попытке открыть каталог с открытыми файлами он не работает. Можете ли вы помочь мне найти способ удалить папку, несмотря на открытые файлы
Пиюш Румао
2
Это не приведет к удалению непустых подкаталогов.
Панг