Java实现文件拷贝(单线程与多线程)
作者:互联网
Java实现文件拷贝(单线程与多线程)
- 将一个文件拷贝到另一个文件目录下,单线程实现涉及到文件IO的知识,下面是我写的源代码:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class SingleCopy {
public static void main(String[] args) {
long a=System.currentTimeMillis();//程序开始执行的时间
RandomAccessFile srcFile=null;
RandomAccessFile destFile=null;
try {
//定义原文件路径和目标文件路径
srcFile=new RandomAccessFile("E:\\学习资料\\图论\\JavaSE高级\\视频\\字符流.mp4","r");
destFile=new RandomAccessFile("F:\\FileCopy\\字符流.mp4","rw");
long startIndex=0;//源文件中赋值操作开始坐标
long endIndex= srcFile.length();//源文件中赋值操作结束坐标
srcFile.seek(startIndex);//将源文件中的指针移到开始坐标
destFile.seek(startIndex);//将目标文件的指针移到开始坐标
int len=-1;
byte[] bytes=new byte[1024];//1KB
while((len= srcFile.read(bytes))!=-1){
startIndex+=len;
destFile.write(bytes,0,len);
if(startIndex>=endIndex){
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(srcFile!=null||destFile!=null){
try {
//关闭流
srcFile.close();
destFile.close();
} catch (IOException e) {
e.printStackTrace();
}
//方便GC(垃圾回收机制)回收,防止内存泄漏
srcFile=null;
destFile=null;
}
}
System.out.println("单线程拷贝所用时间"+(System.currentTimeMillis()-a)/1000+"秒");//程序执行总共花费时间
}
}
用RandomAccessFile(随机存取文件类)的原因:
- RandomAccessFile可以随机访问文件,类中有一个seek(long p)方法,可以移动文件中的指针,将文件记录指针定位到p位置,这样就可以从p位置进行操作。
- RandomAccessFile是一个双向流,既可以读也可以写。
- 多线程实现:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
class CopyTread extends Thread{
private String src;
private String dest;
private Long startIndex;
private Long endIndex;
private CountDownLatch latch;
public CopyTread(String src, String dest, long startIndex, long endIndex,CountDownLatch latch) {
this.src=src;
this.dest=dest;
this.startIndex=startIndex;
this.endIndex=endIndex;
this.latch=latch;
}
@Override
public void run() {
RandomAccessFile srcFile = null;
RandomAccessFile destFile = null;
try {
//创建原文件和目标文件的随机访问字节流
srcFile = new RandomAccessFile(src, "r");
destFile = new RandomAccessFile(dest, "rw");
srcFile.seek(startIndex);//将源文件中的指针移到开始坐标
destFile.seek(startIndex);//将目标文件的指针移到开始坐标
int len = -1;
byte[] bytes = new byte[1024*1024*10];//每次从源文件中读取10MB内容
while ((len = srcFile.read(bytes)) != -1) {
startIndex += len;
destFile.write(bytes, 0, len);
if (startIndex >= endIndex) {
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (srcFile != null || destFile != null) {
try {
//关闭流
srcFile.close();
destFile.close();
} catch (IOException e) {
e.printStackTrace();
}
//方便GC(垃圾回收机制)回收,防止内存泄漏
srcFile = null;
destFile = null;
}
}
latch.countDown();
}
}
public class TreadCopy {
public static void main(String[] args) throws InterruptedException {
long a = System.currentTimeMillis();
//源文件目录
String src="E:\\学习资料\\图论\\JavaSE高级\\视频\\字符流..mp4";
//目标文件目录
String dest="F:\\FileCopy\\字符流Copy.mp4";
//分copyNum次拷贝,每次一个线程
int copyNum=4;
//主线程来分配每个线程操作的起始坐标和结束坐标
File srcfile=new File(src);
long l= srcfile.length();//源文件的总长度
long len=l/copyNum;//每次copy的长度
CountDownLatch latch=new CountDownLatch(copyNum);//定义一个线程计时器
for (int i = 0; i < copyNum-1; i++) {
CopyTread copyTread=new CopyTread(src,dest,len*i,len*(i+1),latch);
copyTread.start();
}
CopyTread copyTread=new CopyTread(src,dest,(copyNum-1)*len,l,latch);
copyTread.start();
latch.await();
System.out.println("多线程拷贝所用时间" + (System.currentTimeMillis() - a) / 1000 + "秒");
}
}
- 定义一个CountDownLatch是为了让所有的子线程执行完再执行主线程中latch.await()后的代码,防止主线程比子线程先执行完,打印的时间就不是所有线程执行完的时间。
- 子线程的while循环中的srcFile.read(bytes)可能会读到超过endIndex的数据并写入目标文件,因为每个线程的最后一次执行while循环可能此时endIndex-startIndex的数据量不能装满bytes的空间,这样bytes就会继续从endIndex后的数据中读,直到判断if(startIndex >= endIndex)跳出循环。但这个不用担心,下一个线程进来会从自己的startIndex开始复制数据,虽然可能重复复制上个线程的数据,但这个线程会把这些数据放到目标文件startIndex处,也就是将上次多复制的内容覆盖,所以不会影响结果。
- 执行结果
可以看到执行前目标文件夹中并无拷贝的文件
- 单线程执行结果:
- 多线程执行结果:
可能会出现单线程用时短,这是因为我的电脑只有一个cpu,cpu调度多个线程反而需要花费时间。
标签:Java,srcFile,单线程,destFile,RandomAccessFile,startIndex,线程,len,多线程 来源: https://blog.csdn.net/weixin_44480874/article/details/99413688