381. Java IO API - 控制文件樹遍歷流程
在使用 FileVisitor 遍歷文件系統(tǒng)時,有時候我們并不希望遍歷整個文件樹。例如:
- ? 只查找特定文件或目錄,找到后立即退出
- ?? 跳過特定的子目錄或文件夾分支
- ?? 有選擇地控制哪些兄弟目錄繼續(xù)遍歷,哪些不再訪問
Java 提供了 FileVisitResult 枚舉來讓我們控制這些流程。
?? FileVisitResult枚舉值詳解
| 枚舉常量 | 含義 | 應(yīng)用場景 |
|---|---|---|
CONTINUE |
繼續(xù)遍歷 | 默認(rèn)行為,進(jìn)入下一級目錄或繼續(xù)訪問兄弟節(jié)點 |
TERMINATE |
終止遍歷 | 找到目標(biāo)文件/目錄后立即停止遍歷 |
SKIP_SUBTREE |
跳過當(dāng)前目錄及其子樹 | 不進(jìn)入當(dāng)前目錄,適合用來排除不必要的分支 |
SKIP_SIBLINGS |
跳過當(dāng)前目錄的所有兄弟節(jié)點 | 當(dāng)前目錄訪問結(jié)束后,不再訪問同級的其他目錄 |
?? 示例 1:跳過名為 SCCS 的目錄
我們可能不希望遍歷一些臨時目錄或版本控制目錄(如 SCCS、.git、node_modules 等),這時可以在 preVisitDirectory() 中使用 SKIP_SUBTREE:
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (dir.getFileName().toString().equals("SCCS")) {
// ?? 跳過該目錄及其子目錄
return SKIP_SUBTREE;
}
return CONTINUE;
}
?? 補充說明:
-
SKIP_SUBTREE只跳過當(dāng)前目錄及其下的子內(nèi)容,不影響同級目錄的遍歷 - 適合用于排除結(jié)構(gòu)性目錄(如緩存、構(gòu)建輸出)
?? 示例 2:一旦找到目標(biāo)文件立即退出
假設(shè)我們要查找某個文件名匹配的文件(如 "config.yml"),并在找到后立刻停止遍歷整個文件樹,可以使用 TERMINATE:
Path lookingFor = Paths.get("config.yml");
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.getFileName().equals(lookingFor)) {
System.out.println("? Found target file: " + file);
return TERMINATE;
}
return CONTINUE;
}
?? 補充說明:
-
TERMINATE會立刻中止遍歷 - 所有后續(xù)的
visitFile、preVisitDirectory、postVisitDirectory都不會再被調(diào)用
?? 示例 3:跳過所有兄弟目錄
有時候我們只想進(jìn)入一個特定目錄做操作后,不再訪問同級目錄:
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (dir.getFileName().toString().equals("target")) {
// ?? 不進(jìn)入該目錄,也不訪問其他同級目錄
return SKIP_SIBLINGS;
}
return CONTINUE;
}
或在目錄處理完成后決定不再訪問兄弟節(jié)點:
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
// 完成對某個目錄的處理后終止兄弟目錄遍歷
return SKIP_SIBLINGS;
}
?? 補充說明:
-
SKIP_SIBLINGS是較少使用但非常強力的控制方式 - 使用時要確保對邏輯影響有清晰的認(rèn)識(比如提前終止同級處理)
?? 小技巧:結(jié)合 walkFileTree 精準(zhǔn)控制
EnumSet<FileVisitOption> opts = EnumSet.noneOf(FileVisitOption.class); // 不跟隨符號鏈接
Files.walkFileTree(startingPath, opts, Integer.MAX_VALUE, new MyCustomVisitor());
你可以結(jié)合訪問深度限制、是否跟隨鏈接以及返回值控制整個遍歷策略,實現(xiàn)精準(zhǔn)而高效的文件系統(tǒng)操作。
?? 總結(jié)回顧
| 控制目標(biāo) | 應(yīng)用方法 | 返回值 |
|---|---|---|
| 跳過特定目錄 | 在 preVisitDirectory() 中判斷 |
SKIP_SUBTREE |
| 跳過當(dāng)前目錄及兄弟目錄 | 在 preVisitDirectory() 或 postVisitDirectory() 返回 |
SKIP_SIBLINGS |
| 完全中止遍歷 | 在任意方法中 | TERMINATE |
| 默認(rèn)繼續(xù) | 所有未觸發(fā)控制邏輯時 | CONTINUE |