Java多线程复制大文件

复制大文件思路

将文件等分,分成n部分,交由n个线程去复制。
如何计算文件大小 File().length;

在进行文件写入时按照分块写入,所有必须规定fromFile,toFile,start,end;
其中fromFile为源文件,toFile为保存的文件
start为开始位置,end为结束位置。

主要使用的方法

写入读出设计到IO流,涉及到基础的IO操作
读入时要分块读入,涉及到 InputStream().skip();方法
写入需要分块,这里需要注意InputStream类没有相关跳过,或定位到指定位置,此时使用
RandomAccessFile类,其中seek();可以相当于InputStream跳过skip方法。
剩下就按照普通的IO读取和写入进行相关操作。最后封装到线程中即可。

写在最后

在对文件的IO流进行直接操作,即传值时,需注意skip或seek操作的是同一对象。而不是不同对象。这里极有可能出错,所以传入对象为File,在其内部在获取到io流进行操作,即不会出错。
另对文件进行获取开始和结束时,需注意最后一块的大小。

贴上代码

主Test

public class MyTest {
    public static void main(String[] args) {
        IOTest ioTest = new IOTest();
        String fileName="F:新东方词汇词根+联想记忆法MP3.rar";
        ioTest.Test(5,fileName);
    }


}

IOTest

import java.io.*;
import java.util.ArrayList;

public class IOTest {
    public void Test(int time,String FileName) {
        String fromPathName=FileName;
        String toPathName=null;
        OutputStream outputStream=null;
        InputStream inputStream=null;
        long length;
        File fromfile=new File(fromPathName);
        File tofile=null;
        if (fromfile.exists()){
            toPathName=fromfile.getParent()+"xindongfang\\"+fromfile.getName();
            System.out.println("文件目录:\n"+toPathName);
        }
        tofile=new File(toPathName);
        length=fromfile.length();//文件长度  假如5个线程同时往进写,所以length分成5分
        System.out.println("多线程写入大文件啦  文件大小:"+length);
        ArrayList<Node> arrayList=getNodeList(length,time);
        /**
         * 当一个父类目录存在时,当前文件不存在,打开io流时会自动创建对象
         */
        try {
            inputStream=new FileInputStream(fromPathName);
            for (int i=0;i<time;i++){
                new Thread(new IOThread(fromfile,arrayList.get(i).start,arrayList.get(i).end,tofile)).start();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            if (inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }

        }
    }
    private   ArrayList getNodeList(long length,int time){
        ArrayList<Node> arrayList=new ArrayList<>();
        long split =length/time;
        long start=0;
        for (int i=0;i<time;i++){
            if (i!=time-1){
                arrayList.add(new Node(start,start+split-1));
                start+=split;
            }else {
                arrayList.add(new Node(start,length-1));
            }

            //假设总数为100,  0-49 50-99
        }
        return arrayList;
    }
     class Node{
        long start;
        long end;

        public Node(long start, long end) {
            this.start = start;
            this.end = end;
        }
    }
}

读取写入线程

import java.io.*;

public class IOThread implements Runnable {
    InputStream inputStream = null;
    long start;
    long end;
    RandomAccessFile outputStream;
    File tofile = null;
    File fromFile=null;
    byte[] bytes = new byte[1024];

    public IOThread(File fromFile, long start, long end, File toFile) {
        this.start = start;
        this.end = end;
        this.fromFile=fromFile;
        this.tofile=toFile;
    }
    int length;

    @Override
    public void run() {
        try {
            System.out.println("多线程读取开始了     开始: " + start + " 结束 :" + end + " 写入大小: " + (end - start + 1));

            long sum = end - start + 1;

            inputStream=new FileInputStream(fromFile);
            outputStream=new RandomAccessFile(tofile,"rw");

            inputStream.skip(start);
            outputStream.seek(start);
            while (sum>0) {

                if (sum >= 1024) {
                    inputStream.read(bytes);
                    length=1024;
                    sum-=1024;
                } else {
                    inputStream.read(bytes, 0, (int) sum);
                    length=(int)sum;
                    sum=0;
                }
                outputStream.write(bytes,0,length);
            }


//            outputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值