Як видалити папку з файлами за допомогою Java


104

Я хочу створити та видалити каталог за допомогою Java, але він не працює.

File index = new File("/home/Work/Indexer1");
if (!index.exists()) {
    index.mkdir();
} else {
    index.delete();
    if (!index.exists()) {
        index.mkdir();
    }
}

3
Що сталося, коли ви спробували?
Абімаран Кугатасан

Яке питання?
Анікет Такур

1
індексний файл не видаляється.
Mr.G


1
На жаль, @AniketThakur, такий підхід буде слідувати символічним посиланням та видаляти файли та каталоги, які, можливо, не були призначені.
Ханк Шульц

Відповіді:


99

Java не в змозі видалити папки з даними, що знаходяться в ній. Перед видаленням папки потрібно видалити всі файли.

Використовуйте щось на кшталт:

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

Тоді ви зможете видалити папку, використовуючи index.delete() Неперевірений!


37
Це не видалить непорожні підкаталоги.
Франческо Мензані

13
ви повинні написати рекурсивний метод або використовувати так, FileUtils.deleteDirectoryяк сказав @Francesco Menzani.
EN20

4
Будьте ДУЖЕ обережними. Якщо індекс символічне посилання на інший каталог, ви завершите видалення вмісту іншого каталогу. На жаль, я ще не знайшов хорошого способу виявлення символічних посилань на Windows у Java 6, хоча Java 7 надає Files.isSymbolicLink ().
Хенк Шульц

1
Рішення: вставте цей фрагмент коду в if (!index.delete()) {...}. Потім, якщо індекс є символічним посиланням, він видаляється незалежно від того, чи видається він у ньому вмістом.
Ханк Шульц

Це призведе до викиду NullPointerException, якщо під час читання каталогу є виключення вводу-виводу. Код повинен перевірити, чи entriesнедійсний.
mernst

178

Просто однолінійний.

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

Документація тут



13
гм ... ні. Це однолінійний зв’язок із зовнішньою залежністю, що важливо пам’ятати. Єдиний час, коли використовується така зовнішня залежність, як це просто, це коли ви робите проект особистого дому, або ваша компанія насправді не переймається можливістю позову.
searchchengine27

11
@ searchchengine27, але, схоже, бібліотека перебуває під Apache Commons, тому ризик отримати позов незначний whitesourcesoftware.com/whitesource-blog/… .
simtim

1
@simtim ви цілком пропустите точку. Компанія ніколи не схвалює бібліотеку для використання без команди юристів, що спочатку виконує умови користування та угоди кінцевих користувачів та будь-які інші юридичні документи, пов’язані з бібліотекою. Хтось повинен платити цим адвокатам ... іноді ніхто не хоче, а це означає, що розробник не має права ним користуватися. Чим більша компанія, в якій ви працюєте, тим більше бюрократів вам доведеться пройти.
searchchengine27

19
@ searchchengine27 ні, ви повністю пропускаєте крапку. Компанія, якій потрібна армія юристів, щоб дозволити користуватися апаш-общинами, є абсолютною патологією, і нічого, що не відповідає нормі в світі ІТ. Я ніколи не чув, щоб хто-небудь мав такі проблеми, і якщо у вас є такі проблеми, у вас, швидше за все, доступ до 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
Як виявляється, в цьому є помилка. Якщо інший процес видаляє файли під час циклу, це може спричинити виняток, який слід виловлювати та ігнорувати.
Джефф Ліверман

2
@ 9ilsdx9rvj0lo Замість того, щоб бути химерним, можливо, ви можете надати редагування для обробки символьних посилань. ОП нічого не сказала про символічні посилання у своєму посту. Просто створення та видалення каталогу. Будь ласка, перерахуйте "багато речей, які відсутні". Допоможіть нам.
Perry Tew

@PerryTew Я не хитрий. Я просто вказую, що я повністю не погоджуюся з вашим коментарем щодо того, що відповідь краща, оскільки жодні зовнішні бібліотеки не використовуються. Це не. Є причина, що люди використовують апаш-общи: вам не потрібно самостійно програмувати жодну річ. Символьні посилання - це лише приклад того, що ви пропустите все з нуля.
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 (глибина)" вище, де глибина - глибина дерева каталогів (порівнюючи це рішення з рекурсивними.)
Джефф Лірман

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, який видалить файл, каталог або каталог з файлами та підкаталогами.



23

Використовуючи Apache Commons-IO, він виконує наступну однолінійку:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

Це (трохи) ефективніше, ніж FileUtils.deleteDirectory.


група: 'commons-io', назва: 'commons-io', версія: '2. +' - корисно
Майк-гризун

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()повертається нуль, а не викликати isDirectory().
mernst

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

6

Guava 21+ на допомогу. Використовуйте лише якщо немає символьних посилань, які вказували б на каталог, для видалення.

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

(Це питання добре індексується Google, тому інші люди Usig Guava можуть бути раді знайти цю відповідь, навіть якщо вона зайва іншими відповідями в інших місцях.)


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

3

Ще одним вибором є використання org.springframework.util.FileSystemUtilsвідповідного методу Spring, який буде рекурсивно видаляти весь вміст каталогу.

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

Це зробить роботу!


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

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

Каталог не може просто видалити, якщо в ньому є файли, тому вам може знадобитися видалити файли спочатку, а потім каталог

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


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

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

Він добре працює з каталогом із усіма закритими файлами. Але при спробі роботи в каталозі з відкритими файлами це не працює. Чи можете ви допомогти мені знайти спосіб видалення папки, незважаючи на відкриті файли
Piyush Rumao

2
Це не видалить непорожні підкаталоги.
Панг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.