Java IO API實現(xiàn)文件和目錄移動、復(fù)制和刪除操作
Java IO API - 移動文件或目錄
移動文件或目錄是文件系統(tǒng)操作中的常見需求,Java 提供了非常方便的方法來實現(xiàn)這一操作:Files.move()。
1. 基本用法
Files.move(sourcePath, targetPath);
這行代碼會嘗試將 sourcePath 移動到 targetPath,但如果目標(biāo)路徑已存在,move() 方法將拋出 FileAlreadyExistsException。
2. 常用選項(CopyOption)
你可以傳遞多個選項來定制移動操作,這些選項以可變參數(shù)(varargs)的形式傳入:
Files.move(sourcePath, targetPath, REPLACE_EXISTING, ATOMIC_MOVE);
| 枚舉常量 | 含義說明 |
|---|---|
REPLACE_EXISTING | 如果目標(biāo)已經(jīng)存在,則替換目標(biāo)文件或目錄。對于符號鏈接,會替換鏈接本身。 |
ATOMIC_MOVE | 確保以原子方式移動文件,意味著文件在移動過程中不會出現(xiàn)部分完成的狀態(tài)。 |
3. 移動目錄
- 空目錄可以直接移動。
- 非空目錄的移動操作會依賴操作系統(tǒng)的支持。在 UNIX 系統(tǒng)中,如果目錄在同一分區(qū)內(nèi)進行移動,實際上是通過重命名來實現(xiàn)的,甚至包含子文件的目錄也能被移動。
Path sourceDir = Paths.get("/home/user/dir");
Path targetDir = Paths.get("/home/user/dir_backup");
Files.move(sourceDir, targetDir, REPLACE_EXISTING);
示例:使用ATOMIC_MOVE保證原子操作
import java.nio.file.*;
import static java.nio.file.StandardCopyOption.*;
public class FileMoveDemo {
public static void main(String[] args) {
Path source = Paths.get("example.txt");
Path target = Paths.get("backup/example.txt");
try {
Files.move(source, target, REPLACE_EXISTING, ATOMIC_MOVE);
System.out.println("? 文件成功移動!");
} catch (IOException e) {
System.err.println("? 文件移動失?。? + e.getMessage());
}
}
}
這里的 ATOMIC_MOVE 保證了文件在移動過程中不會被其他進程看到半成品。如果操作系統(tǒng)或文件系統(tǒng)不支持原子操作,會拋出異常。
4. 使用 Varargs 傳遞多個選項
你可以傳入多個 CopyOption 枚舉值來定制操作。例如:
Files.move(source, target, REPLACE_EXISTING, ATOMIC_MOVE);
這會執(zhí)行一個替換目標(biāo)文件且確保原子性的移動操作。
5. 錯誤處理
如果目標(biāo)路徑已存在并且你沒有使用 REPLACE_EXISTING,move() 會拋出 FileAlreadyExistsException。如果操作系統(tǒng)不支持原子操作(尤其是 ATOMIC_MOVE),會拋出 IOException。
try {
Files.move(sourcePath, targetPath, REPLACE_EXISTING);
} catch (FileAlreadyExistsException e) {
System.err.println("? 目標(biāo)文件已存在,未能移動!");
} catch (IOException e) {
System.err.println("? 文件移動失?。? + e.getMessage());
}
6. 原子操作(Atomic Operations)
原子操作意味著整個操作要么完成,要么完全失敗。對于多進程環(huán)境中的文件操作,原子操作非常關(guān)鍵。舉個例子,如果你在復(fù)制文件時發(fā)生了中斷,原子操作可以保證文件要么完全復(fù)制,要么根本不進行任何復(fù)制操作,避免部分完成的狀態(tài)。
小結(jié)
| 操作類別 | 方法 |
|---|---|
| 文件/目錄移動 | Files.move(Path, Path, ...) |
| 移動選項 | REPLACE_EXISTING, ATOMIC_MOVE |
Java IO API - 復(fù)制文件和目錄
在日常開發(fā)中,復(fù)制文件或目錄是非常常見的需求。Java 提供了靈活且強大的 Files.copy() 方法來處理這些操作。
1. 基本用法
Files.copy(sourcePath, targetPath);
這行代碼會嘗試將 sourcePath 復(fù)制到 targetPath,但如果目標(biāo)已存在,會拋出 FileAlreadyExistsException。
2. 常用復(fù)制選項(CopyOption)
你可以使用可變參數(shù)(varargs)形式傳入多個選項:
Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
| 枚舉常量 | 含義說明 |
|---|---|
REPLACE_EXISTING | 如果目標(biāo)已存在則替換。對于符號鏈接,會復(fù)制“鏈接本身”,而非其指向目標(biāo)。 |
COPY_ATTRIBUTES | 盡量復(fù)制原文件的屬性(如修改時間等)。平臺支持情況可能不同。 |
NOFOLLOW_LINKS | 如果源是符號鏈接,僅復(fù)制鏈接本身,而不跟蹤其目標(biāo)。 |
3. 注意:目錄復(fù)制不包含內(nèi)容!
雖然你可以復(fù)制一個目錄:
Files.copy(Paths.get("docs"), Paths.get("docs_copy"));
但是這樣復(fù)制的是空目錄,原始目錄中的子文件和子目錄不會自動復(fù)制。
如果你想復(fù)制整個目錄結(jié)構(gòu),需要使用遞歸或第三方庫(如 Apache Commons IO)。
4. 關(guān)于符號鏈接的行為
默認情況下,復(fù)制符號鏈接會復(fù)制它所指向的目標(biāo)內(nèi)容:
Files.copy(linkPath, copyPath); // 默認會“追蹤”鏈接并復(fù)制目標(biāo)
但如果你只想復(fù)制“鏈接本身”:
Files.copy(linkPath, copyPath, NOFOLLOW_LINKS);
示例:完整文件復(fù)制流程
import java.nio.file.*;
import java.io.IOException;
import static java.nio.file.StandardCopyOption.*;
public class FileCopyDemo {
public static void main(String[] args) {
Path source = Paths.get("example.txt");
Path target = Paths.get("backup/example.txt");
try {
Files.copy(source, target, REPLACE_EXISTING, COPY_ATTRIBUTES);
System.out.println("? 文件復(fù)制成功!");
} catch (IOException e) {
System.err.println("? 復(fù)制失?。? + e.getMessage());
}
}
}
5. 從流中復(fù)制 / 到流中復(fù)制
除了 Path-to-Path 的復(fù)制,Files 類還支持以下操作:
InputStream → File
try (InputStream in = new FileInputStream("source.txt")) {
Files.copy(in, Paths.get("target.txt"), REPLACE_EXISTING);
}
File → OutputStream
try (OutputStream out = new FileOutputStream("output.txt")) {
Files.copy(Paths.get("source.txt"), out);
}
適用于文件上傳、下載等場景!
常見錯誤與建議
| 問題場景 | 建議或說明 |
|---|---|
| 目標(biāo)文件存在導(dǎo)致異常 | 使用 REPLACE_EXISTING |
| 復(fù)制目錄卻發(fā)現(xiàn)是空的 | 遞歸復(fù)制子文件或使用第三方庫 |
| 權(quán)限不足導(dǎo)致 IOException | 檢查文件讀寫權(quán)限 |
| 想保留時間戳等屬性但沒生效 | 盡量使用 COPY_ATTRIBUTES,并測試平臺兼容性 |
小結(jié)
| 操作類別 | 方法 |
|---|---|
| 文件復(fù)制 | Files.copy(Path, Path, ...) |
| 輸入流 → 文件復(fù)制 | Files.copy(InputStream, Path) |
| 文件 → 輸出流復(fù)制 | Files.copy(Path, OutputStream) |
Java IO API - 刪除文件和目錄
在文件操作中,刪除是一個非常常見但需要小心處理的操作,尤其在涉及目錄和符號鏈接時更是如此。
1. 刪除的基本規(guī)則
- 文件(file):可以直接刪除。
- 目錄(directory):必須為空,否則刪除會失敗。
- 符號鏈接(symbolic link):刪除的是鏈接本身,不是它指向的目標(biāo)。
2. 刪除文件的兩種方式
Java 提供了兩種方式來刪除文件或目錄:
方法一:Files.delete(Path path)
此方法用于強制刪除,如果刪除失敗會拋出異常,適合你希望清楚了解失敗原因的場景。
示例代碼:
try {
Files.delete(Paths.get("data.txt"));
System.out.println("? 文件刪除成功!");
} catch (NoSuchFileException e) {
System.err.println("? 文件不存在:" + e.getMessage());
} catch (DirectoryNotEmptyException e) {
System.err.println("?? 目錄不為空,無法刪除:" + e.getMessage());
} catch (IOException e) {
System.err.println("?? 刪除失敗,可能是權(quán)限問題:" + e.getMessage());
}
方法二:Files.deleteIfExists(Path path)
此方法刪除文件,但如果文件不存在也不會拋出異常,返回值為 true 表示刪除成功,false 表示文件本來就不存在。
示例代碼:
Path path = Paths.get("temp.log");
try {
boolean deleted = Files.deleteIfExists(path);
if (deleted) {
System.out.println("? 文件已刪除");
} else {
System.out.println("?? 文件原本就不存在");
}
} catch (IOException e) {
System.err.println("?? 刪除失敗:" + e.getMessage());
}
應(yīng)用場景建議:
| 場景 | 建議方法 |
|---|---|
| 你希望嚴格處理刪除失敗并報告原因 | Files.delete(path) |
| 你只是想安靜地嘗試刪除,不管是否存在 | Files.deleteIfExists(path) |
| 多線程環(huán)境,避免競爭刪除時拋異常 | deleteIfExists 更合適 |
補充提示:遞歸刪除目錄
標(biāo)準 API 沒有提供遞歸刪除目錄的方法,如果你想要刪除非空目錄,需要自己遍歷子文件并逐個刪除。例如:
void deleteRecursively(Path path) throws IOException {
if (Files.isDirectory(path)) {
try (DirectoryStream<Path> entries = Files.newDirectoryStream(path)) {
for (Path entry : entries) {
deleteRecursively(entry);
}
}
}
Files.delete(path);
}
安全注意事項
- 刪除操作不可恢復(fù),請務(wù)必確認路徑。
- 刪除目錄前應(yīng)檢查是否為空,或考慮是否應(yīng)該遞歸刪除。
- 文件可能正在被其他進程使用,導(dǎo)致刪除失敗。
- 有些系統(tǒng)目錄(如 Windows 的
C:\Windows)根本不允許刪除,嘗試會拋異常。
總結(jié)小表
| 方法 | 行為 | 是否拋出異常 |
|---|---|---|
Files.delete(path) | 刪除文件/空目錄 | 是(失敗即拋) |
Files.deleteIfExists() | 刪除,文件不存在也不報錯 | 是(但文件不存在不拋) |
| 遞歸刪除目錄 | 自定義實現(xiàn)遍歷目錄后逐個刪除 | 是(建議封裝) |
到此這篇關(guān)于Java IO API實現(xiàn)文件和目錄移動、復(fù)制和刪除操作的文章就介紹到這了,更多相關(guān)Java文件和目錄操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA插件之彩虹括號Rainbow?Brackets使用介紹
這篇文章主要為大家介紹了IDEA插件之彩虹括號Rainbow?Brackets使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
java開發(fā)分布式服務(wù)框架Dubbo原理機制詳解
這篇文章主要為大家介紹了java開發(fā)分布式服務(wù)框架Dubbo的原理機制詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-11-11
關(guān)于Filter中獲取請求體body后再次讀取的問題
這篇文章主要介紹了關(guān)于Filter中獲取請求體body后再次讀取的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
Spring實現(xiàn)HikariCP連接池的示例代碼
在SpringBoot 2.0中,我們使用默認連接池是HikariCP,本文講一下HikariCP的具體使用,具有一定的參考價值,感興趣的可以了解一下2021-08-08

