CodeGym /課程 /JAVA 25 SELF /複製與移動檔案與資料夾

複製與移動檔案與資料夾

JAVA 25 SELF
等級 40 , 課堂 1
開放

1. 複製檔案

方法 Files.copy:基本語法

在 Java 中,使用來自 java.nio.file 套件的靜態方法 Files.copy 來複製檔案與資料夾。我們已經見過它,現在更深入地了解。Files.copy 的基本語法:

Files.copy(Path source, Path target, CopyOption... options)
  • source:來源檔案或資料夾的路徑。
  • target:要複製到的位置。
  • options:其他選項(例如允許覆寫)。

最簡單的範例

讓我們把當前目錄中的檔案 "input.txt" 複製到資料夾 "backup" 並命名為 "input_backup.txt"

import java.nio.file.*;

public class CopyExample {
    public static void main(String[] args) throws Exception {
        Path source = Path.of("input.txt");
        Path target = Path.of("backup/input_backup.txt");

        Files.copy(source, target);
        System.out.println("檔案已複製!");
    }
}

重要重點:

  • 如果目標檔案已存在,會拋出例外 FileAlreadyExistsException
  • 如果資料夾 "backup" 不存在,方法會拋出錯誤——資料夾必須事先建立!

覆寫式複製

若要允許覆寫目標檔案,請使用選項 StandardCopyOption.REPLACE_EXISTING

Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

表格:主要複製選項

選項 說明
StandardCopyOption.REPLACE_EXISTING
若檔案已存在則覆寫
StandardCopyOption.COPY_ATTRIBUTES
複製屬性(建立日期等)
StandardCopyOption.ATOMIC_MOVE
原子移動(僅搭配 move 使用)

將檔案複製到其他資料夾

在複製前,請先確認目標資料夾已存在:

Path targetDir = Path.of("backup");
if (!Files.exists(targetDir)) {
    Files.createDirectory(targetDir);
}
Files.copy(source, targetDir.resolve("input_backup.txt"), StandardCopyOption.REPLACE_EXISTING);

複製目錄:有個陷阱

方法 Files.copy 只能把資料夾當作「空殼」來複製——其內容(檔案與子資料夾)不會被複製!如果你嘗試複製含檔案的資料夾,只會得到一個空的目錄。若要複製整個目錄及其內容,需要遞迴走訪並手動複製每個檔案(我們會在後續課程再談)。

範例:將檔案從一個資料夾複製到另一個

Path source = Path.of("data/report.txt");
Path target = Path.of("backup/report.txt");

Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

複製時的錯誤處理

複製可能因多種原因失敗:無權限、檔案被占用、空間不足、目標已存在等等。最好一律使用 try-catch

try {
    Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
    System.out.println("複製成功!");
} catch (FileAlreadyExistsException e) {
    System.out.println("檔案已存在:" + target);
} catch (IOException e) {
    System.out.println("輸入/輸出錯誤:" + e.getMessage());
}

2. 移動檔案與資料夾

方法 Files.move:語法

使用以下方法來移動檔案與資料夾:

Files.move(Path source, Path target, CopyOption... options)

其中 source 是(從哪裡移動)的路徑,target 是要放置檔案或資料夾的位置,options 是其他設定(例如取代現有檔案)。

順帶一提,移動不僅是把檔案「搬家」,也可用來重新命名(若只更改檔名)。如果目標資料夾中已有同名檔案,且未指定選項 REPLACE_EXISTING,就會拋出例外。

範例:將檔案移動到另一個資料夾

Path source = Path.of("data/report.txt");
Path target = Path.of("archive/report.txt");

Files.move(source, target);
System.out.println("檔案已移動!");

移動並取代既有檔案

Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);

移動資料夾

Path oldDir = Path.of("data/old_reports");
Path newDir = Path.of("archive/old_reports");

Files.move(oldDir, newDir);

整個資料夾(包含其內的檔案與子資料夾)都會移到新位置。
但如果目標路徑已存在同名資料夾,會發生錯誤。

跨檔案系統移動

如果在不同磁碟間移動檔案(例如從 "C:""D:"),底層會先複製再刪除來源檔案。若該操作不支援原子性,可能會拋出 AtomicMoveNotSupportedException

movecopy 的差異

  • copy:原始檔案/資料夾保留在原處,產生一份副本。
  • move:原始檔案/資料夾被移走,只剩新位置的那一份。

3. 重新命名檔案與資料夾

Java 沒有獨立的「重新命名檔案」方法。重新命名是移動的一種特殊情況:你在同一目錄下提供一個具有不同名稱的新路徑即可。

範例:重新命名檔案

假設我們有檔案 "report.txt",想把它在同一資料夾中改名為 "report_old.txt"

Path dir = Path.of("data");
Path oldName = dir.resolve("report.txt");
Path newName = dir.resolve("report_old.txt");

Files.move(oldName, newName);
System.out.println("檔案已重新命名!");

重要細節

如果目標目錄中已存在你要指定的新名稱之檔案或資料夾,方法會拋出例外。若要繞過此限制並允許取代,可以使用選項 StandardCopyOption.REPLACE_EXISTING

範例:

Path source = Paths.get("old_name.txt");
Path target = Paths.get("new_name.txt");

// 重新命名檔案;若已存在則取代
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);

在此範例中,檔案 "old_name.txt" 會被重新命名為 "new_name.txt"。如果資料夾中已存在同名檔案,它將被覆寫。

重新命名資料夾

Path oldDir = Path.of("data/old_reports");
Path newDir = Path.of("data/archived_reports");

Files.move(oldDir, newDir);
System.out.println("資料夾已重新命名!");

4. 複製、移動與重新命名時的錯誤處理

與檔案系統互動總是存在意外風險。以下是最常見的問題:

檔案已存在。
例外:FileAlreadyExistsException。解法:若要覆寫,請使用 REPLACE_EXISTING

檔案或資料夾被其他行程占用。
例外:IOException。例如檔案在其他程式中開啟。

沒有存取檔案或資料夾的權限。
例外:AccessDeniedException。與使用者權限相關的問題。

跨檔案系統移動。
例外:AtomicMoveNotSupportedException。並非所有檔案系統都支援原子移動。

目標資料夾不存在。
在複製/移動之前,請確認目標資料夾已事先建立!

錯誤處理範例

try {
    Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
} catch (FileAlreadyExistsException e) {
    System.out.println("目標檔案已存在:" + target);
} catch (AtomicMoveNotSupportedException e) {
    System.out.println("不支援原子移動:" + e.getMessage());
} catch (IOException e) {
    System.out.println("移動時發生錯誤:" + e.getMessage());
}

5. 實用建議

檢查目標檔案/資料夾是否存在

在複製或移動之前,先檢查目標路徑是否已被占用:

if (Files.exists(target)) {
    System.out.println("檔案已存在,不進行覆寫。");
} else {
    Files.copy(source, target);
}

使用暫存檔以確保操作安全

在進行複雜操作(例如更新重要檔案)時,常會先使用暫存檔——先複製到暫存檔,再取代正式檔案:

Path temp = Path.of("data/report.tmp");
Files.copy(source, temp, StandardCopyOption.REPLACE_EXISTING);
Files.move(temp, target, StandardCopyOption.REPLACE_EXISTING);

此作法可在發生故障時,將資料遺失的風險降到最低。

範例:在取代前先建立檔案備份

Path file = Path.of("data/report.txt");
Path backup = Path.of("data/report_backup.txt");

if (Files.exists(file)) {
    Files.copy(file, backup, StandardCopyOption.REPLACE_EXISTING);
    System.out.println("已建立備份。");
}

6. 表格:主要方法與選項

操作 Java NIO 方法 特點
複製
Files.copy(source, target, ...)
不會複製資料夾內容!
移動
Files.move(source, target, ...)
可用於重新命名
重新命名
Files.move(source, target, ...)
同一目錄下的新路徑
覆寫
StandardCopyOption.REPLACE_EXISTING
覆寫目標檔案/資料夾
檢查
Files.exists(path)
檢查檔案/資料夾是否存在

7. 複製、移動與重新命名時的常見錯誤

錯誤 №1:嘗試將檔案複製到不存在的資料夾。 若目標目錄未建立,會收到 NoSuchFileException。解法:先使用 Files.createDirectories 建立目錄。

錯誤 №2:試圖使用 Files.copy 直接整個複製資料夾。 該方法只會複製「空殼」,不包含內容。完整複製需要遞迴走訪。

錯誤 №3:未處理目標已存在的情況。 若未傳入 REPLACE_EXISTING,而檔案已存在,會拋出例外。最好明確處理此情境。

錯誤 №4:在新檔名已存在時嘗試重新命名。 同樣會得到 FileAlreadyExistsException。重新命名前可先檢查是否存在。

錯誤 №5:跨檔案系統移動。 有時該操作不支援「原子性」,會拋出 AtomicMoveNotSupportedException。此時請使用非原子移動。

錯誤 №6:權限不足或檔案被鎖定。 如果檔案在其他程式中開啟或缺乏讀寫權限,會得到 AccessDeniedExceptionIOException。請一律處理此類例外。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION