1前書き

この記事では、プレーンJavaでディレクトリを再帰的に削除する方法を説明します。外部ライブラリを使用してディレクトリを削除するためのいくつかの代替案も検討します。


2ディレクトリを再帰的に削除する

Javaにはディレクトリを削除するオプションがあります。ただし、これにはディレクトリを空にする必要があります。そのため、空でない特定のディレクトリを削除するには再帰を使用する必要があります。

  1. 削除するディレクトリの内容をすべて取得します

  2. ディレクトリではない子をすべて削除します(再帰からの終了)

  3. 現在のディレクトリの各サブディレクトリについて、手順1から始めます.

(再帰的ステップ)
。ディレクトリを削除する

この単純なアルゴリズムを実装しましょう。

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

テストクラスの

@ Before

メソッドは

pathToBeDeleted

の場所にサブディレクトリとファイルを含むディレクトリツリーを作成し、

@ After

メソッドは必要に応じてディレクトリをクリーンアップします。

次に、Apacheの

commons-io

とSpring Frameworkの__spring-coreの2つの最も一般的に使用されているライブラリを使用して削除を達成する方法を見てみましょう。 。


3

commons-io


から

FileUtils

を使用する

まず、Mavenプロジェクトに

commons-io

依存関係を追加する必要があります。

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
</dependency>

依存関係の最新版はhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22commons-io%22%20AND%20a%3A%22commons-io%22[にありますここに]。

これで、

FileUtils

を使用して、

deleteDirectory()

などのファイルベースの操作を1つのステートメントで実行できます。

FileUtils.deleteDirectory(file);


4 Spring



FileSystemUtils

を使う

あるいは、Mavenプロジェクトにs

__pring-core

__依存関係を追加することもできます。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>

依存関係の最新版はhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22org.springframework%22%20AND%20a%3A%22spring-core%22[で見つけることができます。ここに。]

削除を実行するには、

FileSystemUtils



deleteRecursively()

メソッドを使用します。

boolean result = FileSystemUtils.deleteRecursively(file);

最近のリリースのJavaでは、以降の節で説明するようなIO操作を実行するための新しい方法が提供されています。


5 Java 7

でNIO2を使用する

Java 7では、

Files

を使用してファイル操作を実行するまったく新しい方法が導入されました。これにより、ディレクトリツリーをたどり、実行するアクションにコールバックを使用することができます。

public void whenDeletedWithNIO2WalkFileTree__thenIsGone()
  throws IOException {

    Path pathToBeDeleted = TEMP__DIRECTORY.resolve(DIRECTORY__NAME);

    Files.walkFileTree(pathToBeDeleted,
      new SimpleFileVisitor<Path>() {
        @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. エントリを処理した後にディレクトリを訪問する

このディレクトリ内のすべてのエントリが
今までに処理(または削除)された
。ファイルにアクセスできません – 失敗の原因となった

IOException

を再スローしてください

ファイル操作の処理に関するNIO2 APIの詳細については、リンク:/java-nio-2-file-api[Java NIO2ファイルAPIの紹介]を参照してください。


6. Java 8



でNIO2を使用する

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



Path



Stream

を返し、逆の順序で並べ替えます。これはディレクトリ自身の前にディレクトリの内容を示すパスを配置します。その後、

Path



File

にマップし、各__Fileを削除します。

7.まとめ

このクイックチュートリアルでは、ディレクトリを削除するさまざまな方法を探りました。再帰を使用して削除する方法を見ましたが、いくつかのライブラリー、イベントを活用するNIO2、および関数型プログラミングパラダイムを採用するJava 8 Path Streamも調べました。

この記事のすべてのソースコードとテストケースはhttps://github.com/eugenp/tutorials/tree/master/libraries[over Github]から入手できます。