CodeGym /課程 /JAVA 25 SELF /操作目錄:建立、刪除、檢視內容

操作目錄:建立、刪除、檢視內容

JAVA 25 SELF
等級 35 , 課堂 4
開放

1. 建立目錄

目錄(也就是資料夾)不只是檔案的容器,更是磁碟上資料組織的基礎。在應用程式中,我們經常為輸入/輸出資料、日誌、暫存檔等建立目錄。現代的 java.nio.file API 讓這些操作更方便且跨平台。

讓我們看看如何透過 FilesPathPaths 來建立、刪除與檢視資料夾內容。

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.getPath.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。請檢查執行環境與存取權限。

1
問卷/小測驗
檔案操作,等級 35,課堂 4
未開放
檔案操作
檔案操作
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION