1. 建立目錄
目錄(也就是資料夾)不只是檔案的容器,更是磁碟上資料組織的基礎。在應用程式中,我們經常為輸入/輸出資料、日誌、暫存檔等建立目錄。現代的 java.nio.file API 讓這些操作更方便且跨平台。
讓我們看看如何透過 Files、Path 與 Paths 來建立、刪除與檢視資料夾內容。
Files.createDirectory(path)
在指定路徑建立一個目錄。若父目錄不存在—將會拋出例外。
import java.nio.file.*;
public class DirectoryDemo {
public static void main(String[] args) throws Exception {
Path dir = Paths.get("testDir");
if (!Files.exists(dir)) {
Files.createDirectory(dir);
System.out.println("目錄已建立: " + dir.toAbsolutePath());
} else {
System.out.println("目錄已存在: " + dir.toAbsolutePath());
}
}
}
如果嘗試建立已存在的目錄,會得到 FileAlreadyExistsException。
Files.createDirectories(path)
建立整條目錄鏈。若某個中間目錄不存在—會自動建立;若部分已存在—不會報錯。
Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("已建立目錄鏈: " + nestedDir.toAbsolutePath());
這就像是你請 Java 不僅蓋房子,還會把門廳與街道一併建好(如果它們尚不存在)。
常見範例:為專案建立目錄結構
假設要把報表存到資料夾 output/reports/2024。別手動逐層檢查每個目錄—請使用 createDirectories。
Path reportsPath = Paths.get("output/reports/2024");
Files.createDirectories(reportsPath);
Java 會自動判斷哪些已存在、哪些需要建立。
2. 刪除檔案與目錄
Files.delete(path)
刪除檔案或空目錄。若目錄非空—將會拋出 DirectoryNotEmptyException。
Path dir = Paths.get("testDir");
try {
Files.delete(dir);
System.out.println("目錄已刪除: " + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
System.out.println("無法刪除:目錄非空!");
}
Files.deleteIfExists(path)
行為與 delete 類似,但當物件不存在時不會丟出錯誤。若有刪除則回傳 true,若物件不存在則回傳 false。
Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
System.out.println("檔案已刪除。");
} else {
System.out.println("找不到檔案,未刪除任何東西。");
}
如何刪除非空目錄?
無法直接刪除非空資料夾。必須先刪除其所有內容(檔案與子目錄),再刪除資料夾本身。可以透過 Files.walkFileTree 遞迴完成:
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
public class DeleteDirectoryRecursively {
public static void main(String[] args) throws IOException {
Path dir = Paths.get("parent");
if (Files.exists(dir)) {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
System.out.println("目錄及其所有內容已刪除。");
}
}
}
如果你剛開始,別被這段程式嚇到—稍後我們會更詳細地講解 walkFileTree。
3. 檢視目錄內容
Files.list(path)
回傳 Stream<Path>—路徑串流。你可以透過 Stream API 處理資料夾內容。每個項目都是檔案或子目錄(不含遞迴!)。
Path dir = Paths.get("output/reports");
if (Files.exists(dir) && Files.isDirectory(dir)) {
try (var stream = Files.list(dir)) {
stream.forEach(path -> System.out.println(path.getFileName()));
}
}
重要細節:必須關閉串流,因此要使用 try‑with‑resources。
範例:輸出檔案與子目錄名稱
Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
stream.forEach(path -> {
String type = Files.isDirectory(path) ? "目錄" : "檔案";
System.out.println(path.getFileName() + " — " + type);
});
}
以集合形式取得檔案清單
List<Path> files = Files.list(reports2024)
.filter(Files::isRegularFile)
.toList();
System.out.println("資料夾中的檔案:");
files.forEach(System.out::println);
重點:Files.list(path) 只會回傳目前目錄(頂層)的內容。若需要遞迴遍歷請使用 Files.walk(path)。
4. 實作:迷你檔案管理器
此工具會建立目錄 mydata/logs、檔案 log1.txt,輸出資料夾內容,接著將一切刪除。
import java.nio.file.*;
import java.io.IOException;
public class MiniFileManager {
public static void main(String[] args) throws IOException {
Path logsDir = Paths.get("mydata/logs");
Files.createDirectories(logsDir);
Path logFile = logsDir.resolve("log1.txt");
Files.writeString(logFile, "嗨,日誌!");
System.out.println("資料夾 " + logsDir + " 的內容:");
try (var stream = Files.list(logsDir)) {
stream.forEach(path -> System.out.println(" - " + path.getFileName()));
}
Files.deleteIfExists(logFile);
Files.deleteIfExists(logsDir);
System.out.println("檔案與資料夾已刪除。");
}
}
程式碼說明:
- Files.createDirectories 會保證整條目錄鏈被建立。
- resolve 是在路徑後附加檔名的便利方式。
- 使用 try‑with‑resources 關閉來自 Files.list 的串流—在 Windows 上尤其重要。
5. 注意事項與細節
檢查是否存在
在建立/刪除之前,先檢查路徑是否存在:
if (!Files.exists(path)) {
Files.createDirectory(path);
}
存取權限
若程式沒有建立/刪除的權限—會得到 AccessDeniedException。例如,以一般使用者在磁碟根目錄建立資料夾幾乎一定會失敗。
空目錄與非空目錄
只能刪除空目錄(Files.delete)。若要連同內容一起刪除,請使用遞迴走訪(walkFileTree)。
跨平台性
API java.nio.file 能在所有主流作業系統上正確運作並考慮路徑分隔符。建立路徑請使用 Paths.get 與 Path.resolve,而不是手動串接字串。
符號連結
在基礎任務中通常不必理會它們,但若遇到既非一般檔案也非目錄的「奇怪」項目—很可能就是符號連結。進階課程我們會再回來討論。
6. 處理目錄時的常見錯誤
錯誤 №1:試圖直接以 Files.delete(path) 刪除非空目錄。 Java 會拋出 DirectoryNotEmptyException。請先刪除內容,再刪除資料夾本身。
錯誤 №2:忘了關閉從 Files.list() 取得的串流。 若不使用 try‑with‑resources,串流會保持開啟,並且在 Windows 上刪除資料夾時可能發生錯誤。
錯誤 №3:未檢查父目錄就建立目錄。 當對 Files.createDirectory 傳入 parent/child,而 parent 不存在時,會導致 NoSuchFileException。請改用 Files.createDirectories。
錯誤 №4:不必要地使用絕對路徑。 在專案內應偏好相對路徑—這樣程式更容易移植。
錯誤 №5:未處理 IOException。 任何與檔案系統相關的操作都可能失敗。請以 try-catch 包裹或將例外向上拋出。
錯誤 №6:嘗試在沒有權限的資料夾建立/刪除。 這種情況會得到 AccessDeniedException。請檢查執行環境與存取權限。
GO TO FULL VERSION