首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 文件/目錄遞歸複製工具類實現 (含 NIO、系統命令、配置驅動)

     編輯:Java 相關知識

功能需求

  • 遞歸複製源目錄下所有文件/子目錄到目標目錄
  • 目標目錄不存在自動創建
  • 支援配置文件指定源/目標/日誌路徑
  • 提供多種複製實現策略 (NIO、系統命令、流複製)
  • 詳細日誌記錄 (控制台 + 文件)

核心類結構


public class FileCopyUtil {
    // 配置屬性
    private static String rootSourcePath;
    private static String rootTargetPath;
    private static String logFilePath;

    // 入口
    public static void main(String[] args) {
        loadConfig();
        copyDirectory(rootSourcePath, rootTargetPath);
    }

    // 遞歸複製目錄
    private static void copyDirectory(String srcDir, String destDir) {
        File target = new File(destDir);
        if (!target.exists()) {
            target.mkdirs();
            log("創建目錄: " + destDir);
        }

        File source = new File(srcDir);
        File[] files = source.listFiles();
        if (files == null) return;

        for (File f : files) {
            String targetPath = destDir + File.separator + f.getName();
            if (f.isFile()) {
                copyFile(f.getAbsolutePath(), targetPath);
            } else if (f.isDirectory()) {
                copyDirectory(f.getAbsolutePath(), targetPath + File.separator);
            }
        }
    }

    // 文件複製:策略 1 - NIO transferTo (零拷貝, 高性能)
    private static void nioCopy(String src, String dest) {
        try (FileChannel in = FileChannel.open(Paths.get(src), StandardOpenOption.READ);
             FileChannel out = FileChannel.open(Paths.get(dest), 
                     StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
            in.transferTo(0, in.size(), out);
        } catch (IOException e) { throw new UncheckedIOException(e); }
    }

    // 文件複製:策略 2 - 系統命令 (Windows copy / Linux cp)
    private static void systemCopy(String src, String dest) {
        try {
            String cmd = System.getProperty("os.name").startsWith("Windows") ?
                "cmd /c copy /y \"" + src + "\" \"" + dest + "\"" :
                "cp -f \"" + src + "\" \"" + dest + "\"";
            Runtime.getRuntime().exec(cmd).waitFor();
        } catch (Exception e) { throw new RuntimeException(e); }
    }

    // 文件複製:策略 3 - 傳統流複製 (兼容性最好)
    private static void streamCopy(String src, String dest) {
        try (InputStream in = new FileInputStream(src);
             OutputStream out = new FileOutputStream(dest)) {
            byte[] buf = new byte[8192];
            int len;
            while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
        } catch (IOException e) { throw new UncheckedIOException(e); }
    }

    // 統一日誌
    private static void log(String msg) {
        System.out.println(msg);
        appendLog(msg + "\r\n");
    }
    private static void appendLog(String content) {
        try (FileWriter fw = new FileWriter(logFilePath, true)) { fw.write(content); }
        catch (IOException e) { e.printStackTrace(); }
    }

    // 載入配置 (ISO-8859-1 → GBK 轉碼處理中文路徑)
    private static void loadConfig() { ... }
}

三種複製策略對比

策略優點缺點適用場景
NIO transferTo零拷貝 (Kernel 空間直接傳輸)、CPU 佔用極低、大文件最快需 Java 1.4+、部分網絡文件系統不支援本地磁盤大文件、高性能要求
系統命令調用 OS 原生優化、支援稀疏文件/屬性保留跨平台命令不同、進程開銷大、難捕獲詳細錯誤特殊文件屬性保留、腳本集成
流複製純 Java、全平台兼容、易於添加進度條/限速/加密用戶態多次拷貝、CPU 佔用高小文件、網絡流、需自定義邏輯

配置文件範例 (config.properties)


rootSourcePath=D:/data/source
rootTargetPath=E:/backup/target
logFilePath=D:/logs/copy.log

注意:Properties 文件讀取默認 ISO-8859-1,中文路徑需轉碼:


String val = new String(prop.getProperty("key").getBytes("ISO-8859-1"), "GBK");

生產級增強建議

  1. 斷點續傳:記錄已複製文件大小/校驗和,支持中斷恢復
  2. 並發複製:使用 ExecutorService + BlockingQueue 多線程複製,控制並發度
  3. 完整性校驗:複製後比對 MD5/SHA256,確保數據無損
  4. 軟鏈接/權限/時間戳保留:NIO.2 Files.copy(src, dest, StandardCopyOption.COPY_ATTRIBUTES)
  5. 進度監控:FileChannel.transferTo 無進度回調,流複製可自行統計字節數發布事件
  6. 錯誤重試:網絡抖動導致的暫時性失敗自動重試 (指數退避)

現代替代方案 (Java 12+)


// 一行代碼遞歸複製 (不跟隨軟鏈接)
Files.walkFileTree(Paths.get(src), new SimpleFileVisitor<Path>() {
    @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        Files.copy(file, Paths.get(dest).resolve(src.relativize(file)), 
                   StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
        return FileVisitResult.CONTINUE;
    }
    @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        Files.createDirectories(Paths.get(dest).resolve(src.relativize(dir)));
        return FileVisitResult.CONTINUE;
    }
});

總結

文件複製看似簡單,生產環境需考慮性能策略選擇、跨平台兼容、異常重試、完整性校驗、元數據保留、並發控制。NIO.2 Files.walkFileTree + Files.copy 是現代 Java 標準解法;歷史項目維護中,本文提供的三策略工具類可平滑過渡。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved