下面的四個方法都可以刪除檔案或資料夾。
它們的共同點是:
當資料夾中包含子檔案的時候都會刪除失敗,也就是說這四個方法只能刪除空資料夾。
//delete是立即執行刪除,而deleteOnExit是程式退出虛擬機器時才會刪除。
File類別的delete()
#File類別的deleteOnExit()
:當虛擬機器終止時,刪除File物件表示的檔案或目錄,如果表示的是目錄,則需要保證目錄是空的,否則無法刪除,無回傳值。
Files.delete(Path path)
:刪除位於作為參數傳遞的路徑上的檔案。對於其他檔案系統操作,此方法可能不是原子的。如果檔案是符號鏈接,則將刪除符號鏈接本身而不是鏈接的最終目標。如果檔案是目錄,則此方法僅在目錄為空時才刪除該檔案。
Files.deleteIfExists(Path path)
要注意的是:
#傳統IO中的File類別和NIO中的Path類別既可以代表文件,也可以代表資料夾。
- | #說明 | #成功的回傳值 | #是否能判別資料夾不存在導致失敗 | 是否能判別資料夾不為空導致失敗 |
---|---|---|---|---|
#File類別的delete( ) | 傳統IO | true | 不能(返回false) | 不能(返回false) |
File類別的deleteOnExit() | 傳統IO,這是個坑,避免使用 | |||
不能,但不存在就不會去執行刪除 | #不能(返回void) | Files.delete(Path path) | NIO,推薦使用 |
DirectoryNotEmptyException
NIO | true | false |
---|---|---|
File.delete()和Files.delete(Path path)比較 | 區別: | |
- | -File.delete() | Files.delete(Path path) |
JDK | JDK1.0 | |
#來源 | java.io.File物件的實例方法 | |
參數 | #無參考 | |
回傳值 | boolean | |
#異常宣告 | 無宣告 | |
檔案不存在 | 不拋出例外,回傳false | |
刪除非空目錄 | #無法刪除,傳回false |
先造数据
private void createMoreFiles() throws IOException { Files.createDirectories(Paths.get("D:\data\test1\test2\test3\test4\test5\")); Files.write(Paths.get("D:\data\test1\test2\test2.log"), "hello".getBytes()); Files.write(Paths.get("D:\data\test1\test2\test3\test3.log"), "hello".getBytes()); }
使用walkFileTree方法遍历整个文件目录树,使用FileVisitor处理遍历出来的每一项文件或文件夹
FileVisitor的visitFile方法用来处理遍历结果中的“文件”,所以我们可以在这个方法里面删除文件
FileVisitor的postVisitDirectory方法,注意方法中的“post”表示“后去做……”的意思,所以用来文件都处理完成之后再去处理文件夹,所以使用这个方法删除文件夹就可以有效避免文件夹内容不为空的异常,因为
在去删除文件夹之前,该文件夹里面的文件已经被删除了。
@Test void testDeleteFileDir5() throws IOException { createMoreFiles(); Path path = Paths.get("D:\data\test1\test2"); Files.walkFileTree(path, new SimpleFileVisitor<Path>() { // 先去遍历删除文件 @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); System.out.printf("文件被删除 : %s%n", file); return FileVisitResult.CONTINUE; } // 再去遍历删除目录 @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); System.out.printf("文件夹被删除: %s%n", dir); return FileVisitResult.CONTINUE; } } ); }
下面的输出体现了文件的删除顺序
文件被删除 : D:\data\test1\test2\test2.log
文件被删除 : D:\data\test1\test2\test3\test3.log
文件夹被删除 : D:\data\test1\test2\test3\test4\test5
文件夹被删除 : D:\data\test1\test2\test3\test4
文件夹被删除 : D:\data\test1\test2\test3
文件夹被删除 : D:\data\test1\test2
我们既然可以遍历出文件夹或者文件,我们就可以在处理的过程中进行过滤。比如:
按文件名删除文件或文件夹,参数Path里面含有文件或文件夹名称
按文件创建时间、修改时间、文件大小等信息去删除文件,参数BasicFileAttributes 里面包含了这些文件信息。
如果你对Stream流语法不太熟悉的话,这种方法稍微难理解一点,但是说实话也非常简单。
使用Files.walk遍历文件夹(包含子文件夹及子其文件),遍历结果是一个Stream
对每一个遍历出来的结果进行处理,调用Files.delete就可以了。
@Test void testDeleteFileDir6() throws IOException { createMoreFiles(); Path path = Paths.get("D:\data\test1\test2"); try (Stream<Path> walk = Files.walk(path)) { walk.sorted(Comparator.reverseOrder()) .forEach(DeleteFileDir::deleteDirectoryStream); } } private static void deleteDirectoryStream(Path path) { try { Files.delete(path); System.out.printf("删除文件成功:%s%n",path.toString()); } catch (IOException e) { System.err.printf("无法删除的路径 %s%n%s", path, e); } }
问题:怎么能做到先去删除文件,再去删除文件夹?
利用的是字符串的排序规则,从字符串排序规则上讲,“D:\data\test1\test2”一定排在“D:\data\test1\test2\test2.log”的前面。
所以我们使用“sorted(Comparator.reverseOrder())”把Stream顺序颠倒一下,就达到了先删除文件,再删除文件夹的目的。
下面的输出,是最终执行结果的删除顺序。
删除文件成功:D:\data\test1\test2\test3\test4\test5
删除文件成功:D:\data\test1\test2\test3\test4
删除文件成功:D:\data\test1\test2\test3\test3.log
删除文件成功:D:\data\test1\test2\test3
删除文件成功:D:\data\test1\test2\test2.log
删除文件成功:D:\data\test1\test2
传统的通过递归去删除文件或文件夹的方法就比较经典了
//传统IO递归删除 @Test void testDeleteFileDir7() throws IOException { createMoreFiles(); File file = new File("D:\data\test1\test2"); deleteDirectoryLegacyIO(file); } private void deleteDirectoryLegacyIO(File file) { File[] list = file.listFiles(); //无法做到list多层文件夹数据 if (list != null) { for (File temp : list) { //先去递归删除子文件夹及子文件 deleteDirectoryLegacyIO(temp); //注意这里是递归调用 } } if (file.delete()) { //再删除自己本身的文件夹 System.out.printf("删除成功 : %s%n", file); } else { System.err.printf("删除失败 : %s%n", file); } }
需要注意的是:
listFiles()方法只能列出文件夹下面的一层文件或文件夹,不能列出子文件夹及其子文件。
先去递归删除子文件夹,再去删除文件夹自己本身。
以上是如何在Java中刪除檔案或資料夾?的詳細內容。更多資訊請關注PHP中文網其他相關文章!