应用多线程解决文件拷贝加进度条项目
Posted j-1-z-2-s-3
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了应用多线程解决文件拷贝加进度条项目相关的知识,希望对你有一定的参考价值。
大家好!!! 这周给你们分享关于文件拷贝和附加进度条(百分比)的制作,博主也是才接触多线程 所以如果有看到这篇博客的大牛 还望提提建议 分享分享关于多线程的经验
废话不多说 直接上代码!!!(这里有2种做法 我自己的和我老师的,大家可以都看看 选择容易接受的 虽然我感觉我做的比我们老师的做法复杂很多)
这是我的做法:
public class Exp2 extends Thread{
/**
* 总字节数
*/
static double bytes;
static double bytex;
/**
* 当前字节数
*/
static double newbytes;
@Override
public void run() {
while(true){
String progress = NumberFormat.getPercentInstance().format(1-(newbytes/bytex));
System.out.println(progress);
try {
sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 主方法实现拷贝
* @param args
* @throws IOException
* @throws InterruptedException
*/
public static void main(String[] args) throws IOException, InterruptedException {
File source = new File("E:\\音乐\\周杰伦-半岛铁盒(超清).mp4");
File targetDir = new File("E:\\Temp");
File file = new File(targetDir,source.getName());
InputStream is = new FileInputStream(source);
OutputStream os = new FileOutputStream(file);
int len = 0;
byte[] b = new byte[1024];
bytes = source.length();
bytex = bytes;
Exp2 ex = new Exp2();
ex.setDaemon(true);
ex.start();
while((len = is.read(b)) != -1){
os.write(b,0,len);
newbytes = bytes - b.length;
bytes = newbytes;
}
os.close();
is.close();
System.out.println("复制成功");
}
开始分析代码
我们先整理一下思路 如果是只用拷贝文件那么就很简单了 但是怎么加进度条呢?
就是说 , 怎么把进度条的进度与文件拷贝的进度联系起来 这应该算一个难点 你们有什么办法吗?
答案是把拷贝文件当前的字节数传给另一个进度条线程 有了基本思路我们就好实现功能了.我的做法是把拷贝当做一个主线程(main方法本身就是个线程) 然后在创建一个进度条线程 不停地统计当前(1-字节数和总字节数之比) 注意:当前字节数和总字节数一定要定义成double类型变量 因为如果是整型的话 得到的进度会一直是0 而且建议大家在使用多线程的时候尽量不要用static修饰变量 因为多个线程访问同一数据会导致并发数据异常 但是这个项目就无所谓了 因为main方法根本就没用到我们定义的static变量 所以不会引起数据异常 这里必须定义一个临时变量 用以时刻更新新的字节数
还有就是一定要在设置守护线程(在主线程结束后 守护线程也会跟着结束)之后 再启动线程
下面是我们柴老师的做法:
public class FileCopyByThread extends Thread{
private File source;
private File target;
//总大小
private double totalSize;
//当前大小
private double currentSize;
public FileCopyByThread(File source, File target) {
super();
this.source = source;
this.target = target;
}
@Override
public void run() {
try(
FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target);
){
//获取文件的实际大小
totalSize = source.length();
byte[] b = new byte[1024];
int len = 0;
//read() 读取一个字节 返回字节内容
//read(byte[] b) 将读取的数据装入字节数组 返回真实的读取长度
System.out.println(getName() + "开始拷贝:" + source.getName());
ProgressListener pl = new ProgressListener();
//设置当前线程为守护线层
pl.setDaemon(true);
pl.start();
while((len = fis.read(b))!= -1){
fos.write(b, 0, len);
currentSize += len;
}
System.out.println("拷贝完成");
}catch (IOException e) {
e.printStackTrace();
}
}
/**
* 计算文件拷贝线程
* @author 雷神
*
*/
class ProgressListener extends Thread {
@Override
public void run() {
while(true) {
//计算进度
double d =currentSize / totalSize;
//将浮点的进度格式化为百分比
String progress = NumberFormat.getPercentInstance().format(d);
System.out.println("拷贝进度:" + progress);
try {
sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
File source = new File("E:\\音乐\\周杰伦-半岛铁盒(超清).mp4");
File target = new File("E:\\Temp\\周杰伦-半岛铁盒(超清).mp4");
new FileCopyByThread(source, target).start();
}
}
柴哥这里定义了一个内部类 当时我没想到内部类,定义内部类的话这样数据就共享了,还有就是柴哥是直接用一个全局变量计算当前的字节数(我当时是真不知道还有 +=len来统计当前字节数的操作,之前对len这个变量一直处于半知半解的状态),最后将得到的double值用NumberFormat格式化成百分数
柴哥这个相当于是我的优化版 但是初学者看到我的代码应该更容易理解一点哈哈哈 最后附上代码运行结果:
大家学到东西了吗? 其实这类问题的难点是想出怎么做 而不是难在具体的实现过程 有时候思维真的比代码熟练度要重要 所以大家有时间一定要多做点算法题 开阔思维!!!
以上是关于应用多线程解决文件拷贝加进度条项目的主要内容,如果未能解决你的问题,请参考以下文章
(68)C#里怎么样提供一个有窗口显示进度条的拷贝目录的功能
delphi CopyFileProgressBar 拷贝文件显示进度条