Java中把一個(gè)文件夾下的所有文件復(fù)制到另一個(gè)文件夾的完整實(shí)現(xiàn)方案
在Java中把一個(gè)文件夾下的所有文件復(fù)制到另一個(gè)文件夾(支持多級(jí)目錄、空文件夾、文件覆蓋等場(chǎng)景),以下是基于Java原生API的完整實(shí)現(xiàn)方案(兼容Java 8+,無需額外依賴):
一、核心實(shí)現(xiàn)思路
- 校驗(yàn)源文件夾:確保源文件夾存在且是合法目錄;
- 創(chuàng)建目標(biāo)文件夾:若目標(biāo)文件夾不存在,自動(dòng)遞歸創(chuàng)建(包括多級(jí)父目錄);
- 遞歸遍歷源文件:遍歷源文件夾下的所有文件/子目錄,區(qū)分文件和目錄分別處理;
- 復(fù)制文件:對(duì)文件使用字節(jié)流/通道復(fù)制,對(duì)目錄遞歸創(chuàng)建并復(fù)制其內(nèi)文件;
- 異常處理:捕獲IO異常,保證復(fù)制過程的健壯性。
二、完整可運(yùn)行代碼
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
/**
* 文件夾復(fù)制工具類(支持多級(jí)目錄、文件覆蓋)
*/
public class FolderCopyUtil {
/**
* 核心方法:復(fù)制源文件夾下的所有文件/目錄到目標(biāo)文件夾
* @param sourceDirPath 源文件夾路徑(如:D:/source)
* @param targetDirPath 目標(biāo)文件夾路徑(如:D:/target)
* @throws IOException IO異常(文件無法讀取/寫入)
*/
public static void copyFolder(String sourceDirPath, String targetDirPath) throws IOException {
File sourceDir = new File(sourceDirPath);
File targetDir = new File(targetDirPath);
// 步驟1:校驗(yàn)源文件夾合法性
if (!sourceDir.exists()) {
throw new IOException("源文件夾不存在:" + sourceDirPath);
}
if (!sourceDir.isDirectory()) {
throw new IOException("路徑不是合法文件夾:" + sourceDirPath);
}
// 步驟2:創(chuàng)建目標(biāo)文件夾(遞歸創(chuàng)建多級(jí)目錄,已存在則無影響)
if (!targetDir.exists()) {
boolean isCreated = targetDir.mkdirs();
if (!isCreated) {
throw new IOException("目標(biāo)文件夾創(chuàng)建失敗:" + targetDirPath);
}
}
// 步驟3:遍歷源文件夾下的所有文件/子目錄
File[] files = sourceDir.listFiles();
if (files == null) { // 源文件夾為空或無讀取權(quán)限
return;
}
for (File file : files) {
String targetFilePath = targetDirPath + File.separator + file.getName();
if (file.isFile()) {
// 步驟4:復(fù)制文件(覆蓋已存在的目標(biāo)文件)
copyFile(file, new File(targetFilePath));
System.out.println("文件復(fù)制成功:" + file.getPath() + " → " + targetFilePath);
} else if (file.isDirectory()) {
// 步驟5:遞歸復(fù)制子目錄
copyFolder(file.getPath(), targetFilePath);
System.out.println("目錄復(fù)制成功:" + file.getPath() + " → " + targetFilePath);
}
}
}
/**
* 輔助方法:復(fù)制單個(gè)文件(使用NIO FileChannel,效率更高)
* @param sourceFile 源文件
* @param targetFile 目標(biāo)文件
* @throws IOException IO異常
*/
private static void copyFile(File sourceFile, File targetFile) throws IOException {
// 覆蓋目標(biāo)文件(若已存在則刪除后重建)
if (targetFile.exists()) {
boolean isDeleted = targetFile.delete();
if (!isDeleted) {
throw new IOException("目標(biāo)文件覆蓋失敗,無法刪除已有文件:" + targetFile.getPath());
}
}
// 使用NIO通道復(fù)制(比傳統(tǒng)字節(jié)流效率更高)
try (FileInputStream fis = new FileInputStream(sourceFile);
FileOutputStream fos = new FileOutputStream(targetFile);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
// 批量傳輸字節(jié),避免逐字節(jié)復(fù)制,提升大文件復(fù)制效率
long transferred = 0;
long fileSize = inChannel.size();
while (transferred < fileSize) {
transferred += inChannel.transferTo(transferred, fileSize - transferred, outChannel);
}
}
}
// 測(cè)試方法
public static void main(String[] args) {
// 替換為你的源文件夾和目標(biāo)文件夾路徑
String sourceDir = "D:/test/source";
String targetDir = "D:/test/target";
try {
copyFolder(sourceDir, targetDir);
System.out.println("文件夾復(fù)制完成!");
} catch (IOException e) {
System.err.println("文件夾復(fù)制失敗:" + e.getMessage());
e.printStackTrace();
}
}
}
三、關(guān)鍵細(xì)節(jié)說明
核心API解析
File.mkdirs():遞歸創(chuàng)建多級(jí)目錄(如目標(biāo)路徑是D:/a/b/c,若a/b不存在,會(huì)自動(dòng)創(chuàng)建),區(qū)別于mkdir()(僅創(chuàng)建單級(jí)目錄);FileChannel.transferTo():NIO通道復(fù)制文件,直接利用操作系統(tǒng)底層IO,比傳統(tǒng)InputStream/OutputStream逐字節(jié)復(fù)制效率高,尤其適合大文件;try-with-resources:自動(dòng)關(guān)閉流/通道,避免手動(dòng)關(guān)閉遺漏導(dǎo)致的資源泄露。
關(guān)鍵特性適配
- 覆蓋目標(biāo)文件:復(fù)制前先刪除已存在的目標(biāo)文件,確保復(fù)制的是最新文件;若需避免覆蓋,可在
copyFile方法中增加判斷:
if (targetFile.exists()) {
System.out.println("目標(biāo)文件已存在,跳過復(fù)制:" + targetFile.getPath());
return;
}
- 空文件夾處理:源文件夾為空時(shí),
listFiles()返回null,直接返回不報(bào)錯(cuò);目標(biāo)空文件夾會(huì)正常創(chuàng)建; - 多級(jí)目錄復(fù)制:通過遞歸調(diào)用
copyFolder,支持復(fù)制源文件夾下的所有子目錄及文件; - 權(quán)限防護(hù):若源文件無讀取權(quán)限/目標(biāo)文件夾無寫入權(quán)限,會(huì)拋出
IOException并提示具體原因。
路徑兼容性
- 使用
File.separator代替硬編碼的/或\,兼容Windows(\)和Linux/Mac(/)系統(tǒng); - 支持絕對(duì)路徑(如
D:/test)和相對(duì)路徑(如./source)。
四、拓展:Java 7+ Files工具類實(shí)現(xiàn)(更簡(jiǎn)潔)
若使用Java 7及以上版本,可借助java.nio.file.Files工具類簡(jiǎn)化代碼,無需手動(dòng)實(shí)現(xiàn)文件復(fù)制邏輯:
import java.io.IOException;
import java.nio.file.*;
public class FolderCopyWithFilesUtil {
public static void copyFolder(String sourceDirPath, String targetDirPath) throws IOException {
Path sourcePath = Paths.get(sourceDirPath);
Path targetPath = Paths.get(targetDirPath);
// 遞歸復(fù)制目錄,配置復(fù)制選項(xiàng)(覆蓋已存在文件)
Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
// 創(chuàng)建目標(biāo)目錄(遞歸)
Path targetDir = targetPath.resolve(sourcePath.relativize(dir));
if (!Files.exists(targetDir)) {
Files.createDirectories(targetDir);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// 復(fù)制文件(覆蓋已存在)
Path targetFile = targetPath.resolve(sourcePath.relativize(file));
Files.copy(file, targetFile, StandardCopyOption.REPLACE_EXISTING);
System.out.println("復(fù)制文件:" + file + " → " + targetFile);
return FileVisitResult.CONTINUE;
}
});
}
public static void main(String[] args) {
String sourceDir = "D:/test/source";
String targetDir = "D:/test/target";
try {
copyFolder(sourceDir, targetDir);
System.out.println("復(fù)制完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
總結(jié)
- 核心方案:
- 基礎(chǔ)版:使用
File+FileChannel實(shí)現(xiàn),兼容性好,適合理解底層邏輯; - 簡(jiǎn)潔版:使用
Files.walkFileTree(Java 7+),代碼更簡(jiǎn)潔,無需手動(dòng)處理遞歸和文件復(fù)制;
- 基礎(chǔ)版:使用
- 關(guān)鍵要點(diǎn):
- 先校驗(yàn)源文件夾合法性,自動(dòng)創(chuàng)建目標(biāo)多級(jí)目錄;
- 區(qū)分文件/目錄,文件用通道復(fù)制(高效),目錄遞歸處理;
- 處理文件覆蓋/權(quán)限問題,保證復(fù)制健壯性;
- 適配場(chǎng)景:支持任意大小文件、多級(jí)目錄、跨系統(tǒng)路徑,滿足絕大多數(shù)文件夾復(fù)制需求。
以上就是Java中把一個(gè)文件夾下的所有文件復(fù)制到另一個(gè)文件夾的完整實(shí)現(xiàn)方案的詳細(xì)內(nèi)容,更多關(guān)于Java把一個(gè)文件夾所有文件復(fù)制到另一個(gè)文件夾的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java中將接口返回的字節(jié)串轉(zhuǎn)為文件詳解
這篇文章主要給大家介紹了關(guān)于Java中將接口返回的字節(jié)串轉(zhuǎn)為文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-11-11
Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解,一些常用的工具類、線程池、緩存,數(shù)據(jù)庫,數(shù)據(jù)庫連接池、賬戶登錄系統(tǒng)、配置文件等程序中可能只允許我們創(chuàng)建一個(gè)對(duì)象,這就需要單例模式,需要的朋友可以參考下2023-12-12

