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);
表格:主要複製選項
| 選項 | 說明 |
|---|---|
|
若檔案已存在則覆寫 |
|
複製屬性(建立日期等) |
|
原子移動(僅搭配 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。
move 與 copy 的差異
- 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 方法 | 特點 |
|---|---|---|
| 複製 | |
不會複製資料夾內容! |
| 移動 | |
可用於重新命名 |
| 重新命名 | |
同一目錄下的新路徑 |
| 覆寫 | |
覆寫目標檔案/資料夾 |
| 檢查 | |
檢查檔案/資料夾是否存在 |
7. 複製、移動與重新命名時的常見錯誤
錯誤 №1:嘗試將檔案複製到不存在的資料夾。 若目標目錄未建立,會收到 NoSuchFileException。解法:先使用 Files.createDirectories 建立目錄。
錯誤 №2:試圖使用 Files.copy 直接整個複製資料夾。 該方法只會複製「空殼」,不包含內容。完整複製需要遞迴走訪。
錯誤 №3:未處理目標已存在的情況。 若未傳入 REPLACE_EXISTING,而檔案已存在,會拋出例外。最好明確處理此情境。
錯誤 №4:在新檔名已存在時嘗試重新命名。 同樣會得到 FileAlreadyExistsException。重新命名前可先檢查是否存在。
錯誤 №5:跨檔案系統移動。 有時該操作不支援「原子性」,會拋出 AtomicMoveNotSupportedException。此時請使用非原子移動。
錯誤 №6:權限不足或檔案被鎖定。 如果檔案在其他程式中開啟或缺乏讀寫權限,會得到 AccessDeniedException 或 IOException。請一律處理此類例外。
GO TO FULL VERSION