Java多线程文件复制功能

Java

这里讲解一个利用Java里面的RandomAccessFile流来实现多线程文件的快速复制功能。

新建一个线程类:

class BpTransf extends Thread {
    private File srcFile = null;
    private File dstFile = null;
    private long posStart;
    private long posEnd;

    /**
     * 线程类的构造方法
     * 
     * @param srcFile
     *            源文件
     * @param dstFile
     *            目标文件
     * @param posStart
     *            复制起点位置
     * @param posEnd
     *            复制终点位置
     * @throws IOException
     */
    public BpTransf(File srcFile, File dstFile, long posStart, long posEnd) throws IOException {
        this.srcFile = srcFile;
        this.dstFile = dstFile;
        if (!dstFile.exists()) {
            dstFile.createNewFile();
        }
        this.posStart = posStart;
        this.posEnd = posEnd;
    }

    @Override
    public void run() {
        RandomAccessFile rafWrite = null;
        RandomAccessFile rafRead = null;
        try {
            rafWrite = new RandomAccessFile(dstFile, "rw");
            rafRead = new RandomAccessFile(srcFile, "r");
        } catch (FileNotFoundException e) {
            System.out.println("没有找到文件!");
        }

        byte[] b = new byte[1024 * 8];// 定义存储数据的字节数组
        int len = 0;
        try {
            rafWrite.seek(posStart);// 设置写文件指针的起点
            rafRead.seek(posStart);// 设置读文件指针的起点
            while ((len = rafRead.read(b)) != -1) {
                rafWrite.write(b, 0, len);
                // 如果文件指针比复制终点位置都大则说明此段复制完毕,可停止复制
                if (rafWrite.getFilePointer() >= posEnd) {
                    // 若复制完毕则提示该线程复制完毕
                    System.out.println(this.getName() + "读取完毕!");
                    break;
                }
            }
            rafWrite.close();
            rafRead.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

利用上面的线程类来复制文件

/**
 * 多线程复制文件
 * 
 */
public class ThreadsBpTransf {

    public static void main(String[] args) throws IOException {
        long startTime=System.currentTimeMillis();
        File srcFile = new File("src.mp4");// 源文件
        File dstFile = new File("dst.mp4");// 目标文件
        long srcSize = srcFile.length();// 源文件长度
        int threadCount = 8;// 线程数量
        // 因为读取源文件时的字节数组大小设置为1024*8所以这里将每个线程复制的长度设定为1024*8的整数倍
        long avg = (srcSize / threadCount) / (1024 * 8) * 1024 * 8;// 将平均值转换为1024*8的倍数
        BpTransf[] bp = new BpTransf[threadCount];// 新建线程数组

        // 若源文件不存在则提示并返回
        if (!srcFile.exists()) {
            System.out.println("源文件不存在。");
            return;
        }
        for (int i = 0; i < threadCount; i++) {
            // 如果是最后一个线程则需要读取末尾所有字节,不是最后一个线程则按照1024*8的倍数分配空间
            if (i == threadCount - 1) {
                bp[i] = new BpTransf(srcFile, dstFile, i * avg, srcSize);
            } else {
                bp[i] = new BpTransf(srcFile, dstFile, i * avg, (i + 1) * avg);
            }
            // 分配每个线程需要读取字节的长度
            bp[i].start();// 启动线程
        }

        for (BpTransf bpTransf : bp) {
            try {
                bpTransf.join();// 判断线程是否复制完毕
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("程序运行完毕。");// 提示程序运行完毕
        // 输出文件前后复制大小
        System.out.println("源文件大小" + srcFile.length() + "" + ",复制后的文件大小:" + dstFile.length());
        
        long time=System.currentTimeMillis()-startTime;
        System.out.println("复制用时"+time/1000+"s");
    }
}