Java `java.io.File` 類提供了文件與目錄路徑的抽象表示,但其 API 顆粒度較細,實際開發中常需組合多個調用才能完成「複製目錄」、「遞刪刪除」、「移動文件」等常見業務。本文提供一個生產級的 OperateFiles 工具類,涵蓋創建、刪除、複製、移動、路徑解析等高頻操作,代碼經過異常處理與資源關閉優化,可直接落地項目。
| 分類 | 方法名 | 功能描述 |
|---|---|---|
| 目錄操作 | newFolder | 創建單級/多級目錄 |
| deleteFolder | 遞歸刪除目錄及其所有內容 | |
| copyFolder | 遞歸複製整個目錄樹 | |
| 文件操作 | newFile | 創建空文件或帶內容創建文件 |
| deleteFile | 刪除指定文件 | |
| copyFile | 字節流複製單個文件 | |
| moveFile / moveFolder | 複製+刪除源實現移動 | |
| 路徑工具 | getExpandedName | 提取文件擴展名 |
| getFilePath | 提取文件所在目錄路徑 | |
| 系統路徑 | getPath | 獲取項目類路徑根目錄 |
public void deleteFolder(String folderPath) {
try {
// 先刪除所有子文件/子目錄
delAllFiles(folderPath);
File dir = new File(folderPath);
if (dir.exists()) {
dir.delete(); // 最後刪除空目錄
}
} catch (Exception e) {
log.error("刪除目錄失敗: {}", folderPath, e);
}
}
private void delAllFiles(String folderPath) {
File file = new File(folderPath);
if (!file.exists() || !file.isDirectory()) return;
String[] files = file.list();
for (String name : files) {
File child = new File(folderPath.endsWith(File.separator)
? folderPath + name : folderPath + File.separator + name);
if (child.isFile()) {
child.delete();
} else if (child.isDirectory()) {
delAllFiles(child.getAbsolutePath()); // 遞歸清空子目錄
deleteFolder(child.getAbsolutePath()); // 刪除空子目錄
}
}
}
關鍵點: 必須先遞歸刪除文件,再刪除空目錄;使用 `File.separator` 保證跨平台兼容。
public void copyFile(String src, String dest) {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest)) {
byte[] buffer = new byte[1024 * 8]; // 8KB 緩衝區
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.flush();
} catch (IOException e) {
log.error("文件複製失敗: {} -> {}", src, dest, e);
}
}
使用 try-with-resources 自動關閉流,緩衝區 8KB 平衡內存與性能。
public void copyFolder(String src, String dest) {
try {
new File(dest).mkdirs(); // 確保目標目錄存在
File srcDir = new File(src);
for (String name : srcDir.list()) {
File srcChild = new File(srcDir, name);
File destChild = new File(dest, name);
if (srcChild.isFile()) {
copyFile(srcChild.getAbsolutePath(), destChild.getAbsolutePath());
} else if (srcChild.isDirectory()) {
copyFolder(srcChild.getAbsolutePath(), destChild.getAbsolutePath()); // 遞歸
}
}
} catch (Exception e) {
log.error("目錄複製失敗: {} -> {}", src, dest, e);
}
}
JDK 7+ 強烈建議使用 `java.nio.file.Files`,代碼更簡潔、支持符號鏈接、屬性讀取、原子操作:
// 複製文件(可選 REPLACE_EXISTING, COPY_ATTRIBUTES)
Files.copy(srcPath, destPath, StandardCopyOption.REPLACE_EXISTING);
// 遞歸複製目錄
Files.walkFileTree(srcDir, new SimpleFileVisitor() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
Files.createDirectories(destDir.resolve(srcDir.relativize(dir)));
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
Files.copy(file, destDir.resolve(srcDir.relativize(file)), REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
});
// 刪除目錄樹
Files.walkFileTree(dir, new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
Files.delete(file); return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
Files.delete(dir); return FileVisitResult.CONTINUE;
}
});
文中代碼已整理為可直接使用的 OperateFiles.java,包含詳細 JavaDoc 註釋與單元測試用例。建議根據項目需求裁剪擴展,或直接遷移至 NIO.2 API 獲取更現代化體驗。