java文件拷贝的集中方式

本文介绍了四种Java文件拷贝方法:普通IO流、BufferedIO、MMap零拷贝以及Sendfile零拷贝,展示了如何使用不同的技术提高文件传输效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

四种拷贝方式

  1. 不同io
  2. buffer io
  3. mmap 零拷贝
  4. sendfile 零拷贝

核心代码

package com.itzhongzi.io;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * @author Administrator
 * @description
 * @since 2024-04-23 19:30
 * <p>
 * 运行方式: java IOTest.java "io" "source" "target"
 */
public class IOTest {

    public static void main(String[] args) {
        String type = args[0];
        String inputFilePath = args[1];
        String outputFilePath = args[2];


        if ("io".equalsIgnoreCase(type)) {
            inputStreamCopyFile(inputFilePath, outputFilePath);
        } else if ("buffer".equalsIgnoreCase(type)) {
            bufferInputStreamCopyFile(inputFilePath, outputFilePath);
        } else if ("mmap".equalsIgnoreCase(type)) {
            mmapInputStreamCopyFile(inputFilePath, outputFilePath);
        } else if ("sendfile".equalsIgnoreCase(type)) {
            sendfileInputStreamCopyFile(inputFilePath, outputFilePath);
        }
    }

    /**
     * 普通io
     *
     * @param inputFilePath
     * @param outputFilePath
     */
    private static void inputStreamCopyFile(String inputFilePath, String outputFilePath) {
        long start = System.currentTimeMillis();
        try (FileInputStream fis = new FileInputStream(inputFilePath);
             FileOutputStream fos = new FileOutputStream(outputFilePath)) {

            byte[] buf = new byte[1024];
            int len;
            ;
            while ((len = fis.read(buf)) != -1) {
                fos.write(buf);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时" + (end - start) + "ms");
    }

    /**
     * buffer io
     *
     * @param inputFilePath
     * @param outputFilePath
     */
    private static void bufferInputStreamCopyFile(String inputFilePath, String outputFilePath) {
        long start = System.currentTimeMillis();
        try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(Paths.get(inputFilePath)));
             BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(Paths.get(outputFilePath)));) {

            byte[] buf = new byte[1024];
            int len;
            while ((len = bis.read(buf)) != -1) {
                bos.write(buf);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时" + (end - start) + "ms");
    }

    /**
     * mmap 零拷贝io
     *
     * @param inputFilePath
     * @param outputFilePath
     */
    private static void mmapInputStreamCopyFile(String inputFilePath, String outputFilePath) {
        try (
                FileChannel channelIn = new FileInputStream(inputFilePath).getChannel();
                FileChannel channelOut = new RandomAccessFile(outputFilePath, "rw").getChannel();
        ) {
            long size = channelIn.size();
            System.out.println("mmap size:" + size);

            MappedByteBuffer mappedInByteBuffer = channelIn.map(FileChannel.MapMode.READ_ONLY, 0, size);
            MappedByteBuffer mappedOutByteBuffer = channelOut.map(FileChannel.MapMode.READ_WRITE, 0, size);

            for (int i = 0; i < size; i++) {
                mappedOutByteBuffer.put(mappedInByteBuffer.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * sendfile 零拷贝io
     *
     * @param inputFilePath
     * @param outputFilePath
     */
    private static void sendfileInputStreamCopyFile(String inputFilePath, String outputFilePath) {

        try (
                FileChannel channelIn = new FileInputStream(inputFilePath).getChannel();
                FileChannel channelOut = new FileOutputStream(outputFilePath).getChannel()
                // FileChannel channelOut = new RandomAccessFile(outputFilePath, "rw").getChannel();
        ) {

            // 方式一
            // 针对小于 2G 文件,超过 2G,超出部分会丢弃
            // long transferSize = channelIn.transferTo(0, channelIn.size(), channelOut);

            // 方式二: 针对大于2G的文件,分多次读写
            // 获取文件总大小
            long size = channelIn.size();
            for (long left = size; left > 0; ) {
                // 真实拷贝的长度, size - left 计算下次拷贝的位置
                long transferSize = channelIn.transferTo(size - left, left, channelOut);
                left = size - transferSize;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ITzhongzi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值