Java多线程文件复制功能

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

新建一个线程类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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();
}
}
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* 多线程复制文件
*
*/
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");
}
}
-------------本文结束感谢您的阅读-------------