Hapus Direktori secara Rekursif di Java

1. Perkenalan

Dalam artikel ini, kami akan mengilustrasikan cara menghapus direktori secara rekursif di Java biasa. Kami juga akan melihat beberapa alternatif untuk menghapus direktori menggunakan pustaka eksternal.

2. Menghapus Direktori Secara Rekursif

Java memiliki opsi untuk menghapus direktori. Namun, ini membutuhkan direktori kosong. Jadi, kita perlu menggunakan rekursi untuk menghapus direktori tertentu yang tidak kosong:

  1. Dapatkan semua isi direktori yang akan dihapus
  2. Hapus semua anak yang bukan direktori (keluar dari rekursi)
  3. Untuk setiap subdirektori dari direktori saat ini, mulailah dengan langkah 1 (langkah rekursif)
  4. Hapus direktori

Mari terapkan algoritma sederhana ini:

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

Metode ini dapat diuji menggunakan kasus uji langsung:

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

The @Before metode kelas uji kami menciptakan sebuah pohon direktori dengan subdirektori dan file pada pathToBeDeleted lokasi dan @After metode membersihkan direktori jika diperlukan.

Selanjutnya, mari kita lihat bagaimana kita bisa mencapai penghapusan menggunakan dua perpustakaan yang paling umum digunakan - Apache's commons-io dan spring-core Spring Framework . Kedua pustaka ini memungkinkan kita menghapus direktori hanya dengan menggunakan satu baris kode.

3. Menggunakan FileUtils dari commons-io

Pertama, kita perlu menambahkan dependensi commons-io ke proyek Maven:

 commons-io commons-io 2.5 

Versi terbaru dari ketergantungan tersebut dapat ditemukan di sini.

Sekarang, kita dapat menggunakan FileUtils untuk melakukan operasi berbasis file apa pun termasuk deleteDirectory () hanya dengan satu pernyataan:

FileUtils.deleteDirectory(file);

4. Menggunakan FileSystemUtils dari Spring

Sebagai alternatif, kita dapat menambahkan dependensi s pring-core ke proyek Maven:

 org.springframework spring-core 4.3.10.RELEASE 

Versi terbaru dari ketergantungan tersebut dapat ditemukan di sini.

Kita bisa menggunakan metode deleteRecursively () di FileSystemUtils untuk melakukan penghapusan:

boolean result = FileSystemUtils.deleteRecursively(file);

Rilis terbaru Java menawarkan cara yang lebih baru untuk melakukan operasi IO seperti yang dijelaskan di bagian berikut.

5. Menggunakan NIO2 Dengan Java 7

Java 7 memperkenalkan cara baru untuk melakukan operasi file menggunakan Files . Ini memungkinkan kita untuk melintasi pohon direktori dan menggunakan callback untuk tindakan yang akan dilakukan.

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

Metode Files.walkFileTree () melintasi pohon file dan memancarkan peristiwa. Kita perlu menentukan callback untuk acara ini. Jadi, dalam kasus ini, kami akan menentukan SimpleFileVisitor untuk mengambil tindakan berikut untuk acara yang dihasilkan:

  1. Mengunjungi file - hapus
  2. Mengunjungi direktori sebelum memproses entri - tidak melakukan apa pun
  3. Mengunjungi direktori setelah memproses entri - hapus direktori, karena semua entri di dalam direktori ini akan diproses (atau dihapus) sekarang
  4. Tidak dapat mengunjungi file - lacak kembali IOException yang menyebabkan kegagalan

Silakan merujuk ke Pengantar Java NIO2 File API untuk detail lebih lanjut tentang NIO2 API dalam menangani operasi file.

6. Menggunakan NIO2 Dengan Java 8

Sejak Java 8, Stream API menawarkan cara yang lebih baik untuk menghapus direktori:

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

Di sini, Files.walk () mengembalikan Stream of Path yang kita urutkan dalam urutan terbalik. Ini menempatkan jalur yang menunjukkan konten direktori sebelum direktori itu sendiri. Setelah itu memetakan Path to File dan menghapus setiap File.

7. Kesimpulan

Dalam tutorial singkat ini, kami mempelajari berbagai cara untuk menghapus direktori. Sementara kami melihat bagaimana menggunakan rekursi untuk menghapus, kami juga melihat beberapa perpustakaan, NIO2 memanfaatkan peristiwa dan Java 8 Path Stream menggunakan paradigma pemrograman fungsional.

Semua kode sumber dan kasus uji untuk artikel ini tersedia di GitHub.