import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.time.Duration;
import java.time.Instant;public class Copy2 {
public static void main(String[] args) throws FileNotFoundException {
new Copy2().start(1);
}
public void start(int threadnumber) throws FileNotFoundException {
//1:获取源文件
File source = new File("f:/test/navicat150_premium_cs_x64.exe");
//2:设置目标文件
File dest = new File("f:/test/navicat2.exe");
//3:将文件根据线程数量分成多块
long size = source.length();//获取文件总大小
long end = size / threadnumber;//each = 138926027
//3:拷贝
int begin = 0;
for (int i = 0; i < threadnumber-1; i++,begin+=end) {
CopyThread1 copyThread1 = new CopyThread1(source, dest,begin,end*(i+1));
Thread t1 =new Thread(copyThread1);
t1.start();
}
CopyThread1 copyThread3 = new CopyThread1(source, dest,begin,size);
Thread t3 =new Thread(copyThread3);
t3.start();
}
}
class CopyThread1 implements Runnable{
private File source;
private File dest;
private RandomAccessFile rsource = null;
private RandomAccessFile rdest = null;
private long begin;
private long end;
public CopyThread1(File source, File dest,long begin,long end) throws FileNotFoundException {
this.source = source;
this.dest = dest;
this.begin = begin;
this.end = end;
rsource = new RandomAccessFile(source, "r");
rdest = new RandomAccessFile(dest, "rw");
}
@Override
public void run() {
try {
Instant start = Instant.now();//System.currentTimeMillis();
//移动文件位置指示器
rsource.seek(begin);
rdest.seek(begin);
//从source读取数据
byte catchsize[] = new byte[1024*1024];//内存中开辟1M空间作为缓冲区
int len = 0;
long total =end -begin;//记录当前线程读取的总数
long hasread = 0;
while((len = (rsource.read(catchsize)))!=-1) {
//向目标文件写的时候分三种情况
//第一种情况:没有读完
if((hasread+len)<total) {
rdest.write(catchsize,0,len);
hasread += 1024*1024;
}
//第二种:恰好读完,
if((hasread+len) == total) {
rdest.write(catchsize, 0, len);
break;
}
//第三种情况:读取多了,超过了当前线程应该读取的总数
if((hasread+len)>total) {
rdest.write(catchsize, 0, (int)(total-hasread));
break;
}
}
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println(Thread.currentThread().getName()+"用时"+duration.toMillis());
}catch(Exception ex) {
ex.printStackTrace();
}finally {
try {
rdest.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
rsource.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}