
本文是Java IO總結系列篇的第4篇,前篇的訪問地址如下:
- 總結java中創建并寫檔案的5種方式-JAVA IO基礎總結第一篇
- 總結java從檔案中讀取資料的6種方法-JAVA IO基礎總結第二篇
- 總結java創建檔案夾的4種方法及其優缺點-JAVA IO基礎總結第三篇
如果您閱讀完成,覺得此文對您有幫助,請給我點個贊,您的支持是我不竭的創作動力,
為了方便大家理解,我特意制作了本文對應的視頻:總結洗掉檔案或者檔案夾的7種方法
一、洗掉檔案或檔案夾的四種基礎方法
下面的四個方法都可以洗掉檔案或檔案夾,它們的共同點是:當檔案夾中包含子檔案的時候都會洗掉失敗,也就是說這四個方法只能洗掉空檔案夾,
需要注意的是:傳統IO中的File類和NIO中的Path類既可以代表檔案,也可以代表檔案夾,
- File類的delete()
- File類的deleteOnExit()
- Files.delete(Path path)
- Files.deleteIfExists(Path path);
它們之間的差異:

- 由上面的對比可以看出,傳統IO方法洗掉檔案或檔案夾,再洗掉失敗的時候,最多回傳一個false,通過這個false無法發掘洗掉失敗的具體原因,是因為檔案本身不存在洗掉失敗?還是檔案夾不為空導致的洗掉失敗?
- NIO 的方法在這一點上,就做的比較好,洗掉成功或失敗都有具體的回傳值或者例外資訊,這樣有利于我們在洗掉檔案或檔案夾的時候更好的做程式的例外處理
- 需要注意的是傳統IO中的deleteOnExit方法,筆者覺得應該避免使用它,它永遠只回傳void,洗掉失敗也不會有任何的Exception拋出,所以我建議不要用,以免在你洗掉失敗的時候沒有任何的回應,而你可能誤以為洗掉成功了,
//false只能告訴你失敗了 ,但是沒有給出任何失敗的原因
@Test
void testDeleteFileDir1() {
File file = new File("D:\\data\\test");
boolean deleted = file.delete();
System.out.println(deleted);
}
//void ,洗掉失敗沒有任何提示,應避免使用這個方法,就是個坑
@Test
void testDeleteFileDir2() {
File file = new File("D:\\data\\test1");
file.deleteOnExit();
}
//如果檔案不存在,拋出NoSuchFileException
//如果檔案夾里面包含檔案,拋出DirectoryNotEmptyException
@Test
void testDeleteFileDir3() throws IOException {
Path path = Paths.get("D:\\data\\test1");
Files.delete(path); //回傳值void
}
//如果檔案不存在,回傳false,表示洗掉失敗(檔案不存在)
//如果檔案夾里面包含檔案,拋出DirectoryNotEmptyException
@Test
void testDeleteFileDir4() throws IOException {
Path path = Paths.get("D:\\data\\test1");
boolean result = Files.deleteIfExists(path);
System.out.println(result);
}
歸根結底,建議大家使用java NIO的Files.delete(Path path)和Files.deleteIfExists(Path path);進行檔案或檔案夾的洗掉,
二、如何洗掉整個目錄或者目錄中的部分檔案
上文已經說了,那四個API洗掉檔案夾的時候,如果檔案夾包含子檔案,就會洗掉失敗,那么,如果我們確實想洗掉整個檔案夾,該怎么辦?
前提準備
為了方便我們后面進行試驗,先去創建這樣一個目錄結構,“.log”結尾的是資料檔案,其他的是檔案夾

可以使用代面的代碼進行創建
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());
}
2.1. walkFileTree與FileVisitor
- 使用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 里面包含了這些檔案資訊,
2.2.Files.walk
如果你對Stream流語法不太熟悉的話,這種方法稍微難理解一點,但是說實話也非常簡單,
- 使用Files.walk遍歷檔案夾(包含子檔案夾及子其檔案),遍歷結果是一個
Stream<Path> - 對每一個遍歷出來的結果進行處理,呼叫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
2.3.傳統IO-遞回遍歷洗掉檔案夾
傳統的通過遞回去洗掉檔案或檔案夾的方法就比較經典了
//傳統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()方法只能列出檔案夾下面的一層檔案或檔案夾,不能列出子檔案夾及其子檔案,- 先去遞回洗掉子檔案夾,再去洗掉檔案夾自己本身
歡迎關注我的博客,里面有很多精品合集
- 本文轉載注明出處(必須帶連接,不能只轉文字):字母哥博客,
覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! ,另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注,
- 《手摸手教你學Spring Boot2.0》
- 《Spring Security-JWT-OAuth2一本通》
- 《實戰前后端分離RBAC權限管理系統》
- 《實戰SpringCloud微服務從青銅到王者》
- 《VUE深入淺出系列》
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/27427.html
標籤:Java
