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

Java 文件複製性能大比拚:四種 I/O 方式實測與分析

     編輯:Java 相關知識

測試環境

  • 檔案:1.mp3 (約 100MB)
  • JDK:1.8+
  • OS:Windows 10 / SSD

四種實作方式

public class FileCopyBenchmark {

    // 1. 單字節讀寫 (最慢)
    public static void copyByte(File src, File dest) throws IOException {
        try (FileInputStream in = new FileInputStream(src);
             FileOutputStream out = new FileOutputStream(dest)) {
            int b;
            while ((b = in.read()) != -1) out.write(b);
        }
    }

    // 2. 字節陣列讀寫 (10KB 緩衝)
    public static void copyByteArray(File src, File dest) throws IOException {
        try (FileInputStream in = new FileInputStream(src);
             FileOutputStream out = new FileOutputStream(dest)) {
            byte[] buf = new byte[10 * 1024];
            int len;
            while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
        }
    }

    // 3. 緩衝流單字節 (BufferedInputStream/OutputStream)
    public static void copyBufferedByte(File src, File dest) throws IOException {
        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
             BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest))) {
            int b;
            while ((b = in.read()) != -1) out.write(b);
        }
    }

    // 4. 緩衝流 + 字節陣列 (推薦生產用)
    public static void copyBufferedArray(File src, File dest) throws IOException {
        try (FileInputStream in = new FileInputStream(src);
             BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest))) {
            byte[] buf = new byte[10 * 1024];
            int len;
            while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
        }
    }
}

實測結果 (100MB 檔案)

方式耗時 (ms)相對性能分析
單字節~90,0001x (基準)每字節一次系統調用,極大開銷
字節陣列 (10KB)~402250x減少系統調用,用戶態緩衝
緩衝流單字節~550160x內核緩衝有效,但單字節寫入仍頻繁調用
緩衝流 + 陣列~303000x雙重緩衝 + 批量寫入,最快

核心結論

  1. 絕對不要用單字節讀寫 (read()/write(int)) 處理大文件。
  2. 字節陣列是性能關鍵:應用層緩衝減少 JNI/系統調用次數。
  3. BufferedOutputStream 比 BufferedInputStream 更關鍵:聚合寫入減少磁碟 I/O。
  4. 實務上推薦 NIO FileChannel.transferTo/transferFrom (零拷貝) 或 Files.copy() (JDK 7+),性能更優且代碼最簡潔:
// 現代最佳實踐 (零拷貝,內核態直接傳輸)
Files.copy(src.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);

補充:NIO transferTo 實測

public static void copyNio(File src, File dest) throws IOException {
    try (FileChannel in = FileChannel.open(src.toPath(), StandardOpenOption.READ);
         FileChannel out = FileChannel.open(dest.toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
        in.transferTo(0, in.size(), out);
    }
}

通常比 Buffered+Array 快 10%-30%,且 CPU 佔用極低。

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