java本地文件多线程拷贝

发布时间 2023-10-03 10:13:08作者: 斌哥的小弟

简单介绍:本地文件多线程拷贝是指通过多个线程同时进行文件复制操作。传统的文件复制操作往往是串行进行的,当需要复制单个大文件时,复制速度往往会比较慢。而采用多线程进行文件拷贝可以提高效率。通过同时创建多个线程,每个线程负责复制不同的文件或者不同的文件片段,可以充分利用计算机资源,加快文件复制速度。

 

核心思想:创建三个用于拷贝文件的线程,通过随机访问文件对象的seek方法和其他必要的读写流,来设置每个线程在拷贝文件中开始写和在被拷贝文件的开始读的位置。

 

核心代码:

public class Test {
    private static final String FILE_PATH = "被拷贝文件的路径";
    private static final String SAVE_PATH = "拷贝文件的路径";
    private static final int NUM_THREADS = 3; //假设由三个线程下载文件

    public static void main(String[] args) {
        try {
            File file = new File(FILE_PATH);
            long fileSize = file.length();
            long chunkSize = fileSize / NUM_THREADS;

            for (int i = 0; i < NUM_THREADS; i++) {
                //设定三个线程在文件里下载的起始位置
                long startByte = i * chunkSize;
                long endByte = (i == NUM_THREADS - 1) ? fileSize - 1 : (i + 1) * chunkSize - 1; /*条件只对于最后一个thread为真,此时直接将文件的最后一个字节设置最后一个线程的末索引,应付文件length除以三不能整除的情况*/

                Thread mergerThread = new MergerThread(FILE_PATH, SAVE_PATH, startByte, endByte);
                mergerThread.start();
            }

            System.out.println("合并文件完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MergerThread extends Thread {
    private String filePath;
    private String savePath;
    private long startByte;
    private long endByte;

    public MergerThread(String filePath, String savePath, long startByte, long endByte) {
        this.filePath = filePath;
        this.savePath = savePath;
        this.startByte = startByte;
        this.endByte = endByte;
    }

    public void run() {
        try {
            RandomAccessFile inputFile = new RandomAccessFile(filePath, "r");
            RandomAccessFile outputFile = new RandomAccessFile(savePath, "rw");
            //设置读写文件的起始位置
            inputFile.seek(startByte);
            outputFile.seek(startByte);

            byte[] buffer = new byte[1024 * 1024];   //设置1MB缓冲区,存储读取的数据并写到目标文件
            int bytesRead; //用于保存读出的数据有多少的变量
            long bytesToRead = endByte - startByte + 1; //这个线程还剩多少字节需要读
            //while里面,要判断read方法返回了-1并同时获取已经读了多少字节
            while (bytesToRead > 0 && (bytesRead = inputFile.read(buffer, 0, (int)  bytesToRead)) != -1) {
                outputFile.write(buffer, 0, bytesRead);
                bytesToRead -= bytesRead;
            }

            inputFile.close();
            outputFile.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}