Рубрики
Без рубрики

Рекурсивное удаление каталога в Java

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

Автор оригинала: baeldung.

1. введение

В этой статье мы проиллюстрируем, как рекурсивно удалить каталог в обычной Java. Мы также рассмотрим некоторые альтернативы удалению каталогов с помощью внешних библиотек.

2. Рекурсивное удаление каталога

В Java есть возможность удалить каталог. Однако для этого требуется, чтобы каталог был пуст. Итак, нам нужно использовать рекурсию для удаления определенного непустого каталога:

  1. Получите все содержимое каталога, подлежащего удалению
  2. Удалите все дочерние элементы, которые не являются каталогом (выход из рекурсии)
  3. Для каждого подкаталога текущего каталога начните с шага 1 (рекурсивный шаг).
  4. Удалите каталог

Давайте реализуем этот простой алгоритм:

boolean deleteDirectory(File directoryToBeDeleted) {
    File[] allContents = directoryToBeDeleted.listFiles();
    if (allContents != null) {
        for (File file : allContents) {
            deleteDirectory(file);
        }
    }
    return directoryToBeDeleted.delete();
}

Этот метод можно протестировать с помощью простого тестового примера:

@Test
public void givenDirectory_whenDeletedWithRecursion_thenIsGone() 
  throws IOException {
 
    Path pathToBeDeleted = TEMP_DIRECTORY.resolve(DIRECTORY_NAME);

    boolean result = deleteDirectory(pathToBeDeleted.toFile());

    assertTrue(result);
    assertFalse(
      "Directory still exists", 
      Files.exists(pathToBeDeleted));
}

Метод @До нашего тестового класса создает дерево каталогов с подкаталогами и файлами в пути для удаления местоположения и @После метод очищает каталог, если требуется.

Далее давайте посмотрим, как мы можем добиться удаления с помощью двух наиболее часто используемых библиотек – Apache commons-io и Spring Framework spring-core. Обе эти библиотеки позволяют нам удалять каталоги, используя всего одну строку кода.

3. Использование имен файлов из commons-io

Во-первых, нам нужно добавить зависимость commons-io в проект Maven:


    commons-io
    commons-io
    2.8.0

Последнюю версию зависимости можно найти здесь .

Теперь мы можем использовать FileUtils для выполнения любых операций на основе файлов, включая удаление каталога() всего одним оператором:

FileUtils.deleteDirectory(file);

4. Использование файловых систем с весны

В качестве альтернативы мы можем добавить зависимость s spring-core в проект Maven:


    org.springframework
    spring-core
    4.3.10.RELEASE

Последнюю версию зависимости можно найти здесь.

Мы можем использовать метод deleteRecursively() в FileSystemUtils для выполнения удаления:

boolean result = FileSystemUtils.deleteRecursively(file);

Последние выпуски Java предлагают новые способы выполнения таких операций ввода-вывода, описанные в следующих разделах.

5. Использование NIO2 С Java 7

Java 7 представила совершенно новый способ выполнения файловых операций с использованием Файлов . Это позволяет нам перемещаться по дереву каталогов и использовать обратные вызовы для выполнения действий.

public void whenDeletedWithNIO2WalkFileTree_thenIsGone() 
  throws IOException {
 
    Path pathToBeDeleted = TEMP_DIRECTORY.resolve(DIRECTORY_NAME);

    Files.walkFileTree(pathToBeDeleted, 
      new SimpleFileVisitor() {
        @Override
        public FileVisitResult postVisitDirectory(
          Path dir, IOException exc) throws IOException {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
        
        @Override
        public FileVisitResult visitFile(
          Path file, BasicFileAttributes attrs) 
          throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }
    });

    assertFalse("Directory still exists", 
      Files.exists(pathToBeDeleted));
}

Метод Files.walkFileTree() пересекает файловое дерево и выдает события. Нам нужно указать обратные вызовы для этих событий. Итак, в этом случае мы определим SimpleFileVisitor , чтобы выполнить следующие действия для сгенерированных событий:

  1. Посещение файла – удалите его
  2. Посещение каталога перед обработкой его записей – ничего не делайте
  3. Посещение каталога после обработки его записей – удалите каталог, так как все записи в этом каталоге были бы обработаны (или удалены) к настоящему времени
  4. Не удалось посетить файл – повторный просмотр Исключение IOException , вызвавшее сбой

Пожалуйста, обратитесь к Введению в файловый API Java NIO2 для получения более подробной информации об API NIO2 для обработки файловых операций.

6. Использование NIO2 С Java 8

Начиная с Java 8, Stream API предлагает еще лучший способ удаления каталога:

@Test
public void whenDeletedWithFilesWalk_thenIsGone() 
  throws IOException {
    Path pathToBeDeleted = TEMP_DIRECTORY.resolve(DIRECTORY_NAME);

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

    assertFalse("Directory still exists", 
      Files.exists(pathToBeDeleted));
}

Здесь Files.walk() возвращает Поток из Пути , который мы сортируем в обратном порядке. Это помещает пути, обозначающие содержимое каталогов, перед самими каталогами. После этого он сопоставляет Путь с Файлом и удаляет каждый Файл.

7. Заключение

В этом кратком руководстве мы рассмотрели различные способы удаления каталога. В то время как мы видели, как использовать рекурсию для удаления, мы также рассмотрели некоторые библиотеки, NIO2, использующие события, и поток путей Java 8, использующий парадигму функционального программирования.

Весь исходный код и тестовые примеры для этой статьи доступны на GitHub .