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

Java 實現大文件分割與合併:IO 流實戰指南

     編輯:Java 綜合教學

前言:為什麼需要文件分割與合併?

在實際開發與運維場景中,大文件傳輸常受限於存儲介質容量或網絡限制。例如:

  • 需將 3GB 文件拷貝至另一台電腦,但手邊只有 1GB 的 SD 卡
  • 上傳百 MB 文件至 FTP 服務器,卻發現單文件大小限制為 10MB

此時,將大文件切割為多個小文件分別傳輸,最後在目標端合併還原,便能輕鬆破解難題。本文將通過完整的 Java 代碼演示如何實現文件的分割與合併功能。

演示環境與文件準備

本文以本地文件 E:\eclipse-jee-juno-win32.zip 為例進行演示。分割前文件完整獨立;分割後將生成多個帶序號的分片文件(如 eclipse-jee-juno-win32_data1.zip、eclipse-jee-juno-win32_data2.zip...)。

分割前的原始文件

分割後生成的多個分片文件

核心實現:文件分割邏輯

分割原理:讀取源文件總長度,按指定份數計算每片大小,循環讀取寫入新文件,直至達到單片大小上限。

/**
 * 文件分割核心方法
 * @param src 源文件對象
 * @param partCount 分割份數
 */
private static void splitFile(File src, int partCount) {
    if (!src.isFile()) return;

    long totalSize = src.length();
    String fileName = src.getName().substring(0, src.getName().lastIndexOf("."));
    String extension = src.getName().substring(src.getName().lastIndexOf("."));
    long partSize = totalSize / partCount; // 每片理論大小

    try (InputStream in = new FileInputStream(src)) {
        byte[] buffer = new byte[10 * 1024 * 1024]; // 10MB 緩衝區
        int bytesRead;

        for (int i = 1; i <= partCount; i++) {
            File partFile = new File(src.getParent(), fileName + "_data" + i + extension);
            try (OutputStream out = new FileOutputStream(partFile)) {
                long written = 0;
                while (written < partSize && (bytesRead = in.read(buffer)) != -1) {
                    int toWrite = (int) Math.min(bytesRead, partSize - written);
                    out.write(buffer, 0, toWrite);
                    written += toWrite;
                }
            }
            System.out.println("已生成分片:" + partFile.getAbsolutePath());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

關鍵點解析

  • 緩衝區大小:設為 10MB,平衡內存佔用與 I/O 效率
  • 精確控制寫入量:通過 written 變量確保每片不超過理論大小,最後一片自動包含剩餘數據
  • 資源管理:使用 try-with-resources 自動關閉流,避免資源洩漏

核心實現:文件合併邏輯

合併原理:按序號順序讀取所有分片,依次追加寫入目標文件。

/**
 * 文件合併核心方法
 * @param partPaths 分片文件路徑陣列(需按正確順序傳入)
 */
private static void mergeFiles(String... partPaths) {
    if (partPaths == null || partPaths.length == 0) return;

    // 從第一個分片推導目標文件名(去除 _dataN 後綴)
    File firstPart = new File(partPaths[0]);
    String targetName = firstPart.getName().replaceFirst("_data\\d+", "") + firstPart.getName().substring(firstPart.getName().lastIndexOf("."));
    File targetFile = new File(firstPart.getParent(), targetName);

    try (OutputStream out = new FileOutputStream(targetFile, true)) { // 追加模式
        byte[] buffer = new byte[10 * 1024 * 1024];
        int bytesRead;

        for (String path : partPaths) {
            File part = new File(path);
            try (InputStream in = new FileInputStream(part)) {
                while ((bytesRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
            }
            System.out.println("已合併分片:" + part.getName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    System.out.println("文件合併完成!輸出文件:" + targetFile.getAbsolutePath());
}

關鍵點解析

  • 追加模式:new FileOutputStream(targetFile, true) 確保後續分片內容追加而非覆蓋
  • 順序敏感:調用方必須保證傳入路徑陣列的順序與分割時的序號一致
  • 異常隔離:單個分片讀取失敗不影響其他分片,但會導致合併結果不完整

完整測試類

public class FileSplitMergeDemo {
    public static void main(String[] args) {
        File srcFile = new File("E:\\eclipse-jee-juno-win32.zip");
        
        // 1. 分割為 3 片
        System.out.println("=== 開始分割 ===");
        splitFile(srcFile, 3);
        
        // 2. 合併還原
        System.out.println("\n=== 開始合併 ===");
        String parent = srcFile.getParent();
        String baseName = srcFile.getName().replaceFirst("\\.zip$", "");
        String ext = ".zip";
        
        String[] parts = new String[3];
        for (int i = 1; i <= 3; i++) {
            parts[i-1] = parent + "\\" + baseName + "_data" + i + ext;
        }
        mergeFiles(parts);
    }
    // ... 此處放入上述 splitFile 與 mergeFiles 方法
}

進階優化方向

  • 校驗機制:分割前計算源文件 MD5,合併後驗證一致性
  • 並行處理:合併階段可使用多線程並發讀取分片(需注意寫入順序同步)
  • 斷點續傳:記錄已合併分片索引,支持中斷後恢復
  • 內存映射:大文件場景下可嘗試 MappedByteBuffer 提升性能

總結

文件分割與合併雖屬基礎 IO 操作,但掌握其核心邏輯——精確控制讀寫邊界、合理設置緩衝區、妥善管理資源釋放——是處理大文件傳輸、分布式存儲、斷點續傳等場景的基石。實際項目中建議封裝為通用工具類,並加入校驗與異常重試機制。

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