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

Java 檔案複製與格式轉換實戰:批量將 .tbi 轉為 .jpg

     編輯:Java 程式設計入門

需求場景

實際專案中常需批量複製檔案並修改副檔名(如醫療影像 .tbi 轉標準 .jpg),需處理目錄遞迴、目標目錄建立、IO 流管理、異常處理等細節。

完整實作程式碼

package com.chen.lucene.image;

import java.io.*;

public class FileFormatConverter {

    /**
     * 批量複製並轉換檔案副檔名
     *
     * @param sourceDir 來源目錄路徑
     * @param targetDir 目標目錄路徑
     * @param oldSuffix 原副檔名(含點,如 ".tbi")
     * @param newSuffix 新副檔名(含點,如 ".jpg")
     * @throws IOException IO 異常
     */
    public void convertAndCopy(String sourceDir, String targetDir,
                               String oldSuffix, String newSuffix) throws IOException {

        File source = new File(sourceDir);
        if (!source.exists() || !source.isDirectory()) {
            throw new IllegalArgumentException("來源目錄不存在或非目錄: " + sourceDir);
        }

        File target = new File(targetDir);
        if (!target.exists()) {
            if (!target.mkdirs()) {
                throw new IOException("無法建立目標目錄: " + targetDir);
            }
        }

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

        for (File file : files) {
            if (file.isFile() && file.getName().endsWith(oldSuffix)) {
                String newName = file.getName().replaceFirst(oldSuffix + "$", newSuffix);
                File destFile = new File(target, newName);
                copyFile(file, destFile);
                System.out.printf("已轉換: %s → %s%n", file.getName(), newName);
            }
        }
    }

    /**
     * 檔案複製核心方法(使用 4KB 緩衝區)
     */
    private void copyFile(File source, File dest) throws IOException {
        try (FileInputStream fis = new FileInputStream(source);
             FileOutputStream fos = new FileOutputStream(dest);
             BufferedInputStream bis = new BufferedInputStream(fis, 4096);
             BufferedOutputStream bos = new BufferedOutputStream(fos, 4096)) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            bos.flush();
        }
    }

    // 測試主程式
    public static void main(String[] args) {
        FileFormatConverter converter = new FileFormatConverter();
        try {
            converter.convertAndCopy(
                "E:/temp/3月份數據包",
                "E:/temp/img",
                ".tbi", ".jpg"
            );
            System.out.println("批量轉換完成!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

關鍵技術點解析

1. 現代 IO 最佳實踐 (Java 7+)

  • try-with-resources:自動關閉流,避免資源洩漏
  • BufferedInputStream/OutputStream:減少系統呼叫次數,提升吞吐量
  • 4KB-8KB 緩衝區:匹配磁碟頁面大小,平衡記憶體與效能

2. 檔名替換的正則陷阱


// 錯誤:replaceAll(".tbi", ".jpg") 會匹配任意字元
// 正確:replaceFirst("\\.tbi$", ".jpg") 或 endsWith + substring
String newName = file.getName().replaceFirst(oldSuffix + "$", newSuffix);

3. 大檔案複製優化方案

方案適用場景優點缺點
標準 IO (本例)中小檔案、跨檔案系統相容性好、可控用戶態/核心態多次拷貝
NIO FileChannel.transferTo大檔案、同檔案系統零拷貝、核心態直傳跨檔案系統可能退化
Files.copy (Java 7+)通用場景API 簡潔、自動選擇最佳策略細節控制較少

NIO 零拷貝版本參考


import java.nio.channels.FileChannel;
import java.nio.file.StandardCopyOption;

public void copyWithNIO(File source, File dest) throws IOException {
    try (FileChannel in = FileChannel.open(source.toPath());
         FileChannel out = FileChannel.open(dest.toPath(),
                 StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
        // 嘗試零拷貝,大檔案分段傳輸避免阻塞
        long transferred = 0;
        long size = in.size();
        while (transferred < size) {
            transferred += in.transferTo(transferred, size - transferred, out);
        }
    }
}

4. 生產環境增強建議

  • 加入進度回呼介面:支援 UI 顯示進度條
  • 實作斷點續傳:記錄已處理檔案清單
  • 使用線程池並行複製:ExecutorService + CompletableFuture
  • 加入校驗碼驗證:MD5/SHA256 確保檔案完整性
  • 統一日誌記錄:SLF4J 替代 System.out

常見坑點總結

  1. 忘記 flush():BufferedOutputStream 需顯式 flush 或靠 close 自動觸發
  2. 路徑分隔符硬編碼:必須用 File.separator 或 Paths.get()
  3. 忽略隱藏檔/權限問題:listFiles() 可能返回 null 或拋 SecurityException
  4. 大檔案 OOM:避免一次性 readAllBytes,必須分塊讀寫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved