版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Seven_deadly_sins/article/details/81603506
看了多线程之后,想着试一下拿多线程写点对象,正好看到书上实例是拿多线程创建多个进度条举例的,加上之前学的IO流,写了一个运用多线程来进行文件拷贝的代码。但是写的过程中,进程数量是自己直接定义的,想着把进程和进度条定义为数组,实现根据使用者输出来定义进程的数量,在创建进度条数组时发现可以创建,但是调用时一直为空,查了查也没找到解决方法。
该代码实现一次同步拷贝4个文件,拷贝时分字节拷贝和字节数组拷贝,如果想要看进度条增长的话建议切换成字节拷贝,因为字节拷贝比较慢,进度显示比较明显。
进度条显示百分比的设计是根据IO流中的File类中查看文件长度(以字节为长度,下同)的length()方法,即复制时每次输出都使用该方法读取当前复制后文件的长度,和原文件的长度进行比较,将得到的比率转换为百分数(因为进度条上数字为int型,所以该百分数应转换为int类型),将实时的比率传递到进度条上(文件传输完成后应将进度条上数字重置为100,因为最后一次拷贝完成时进度条显示可能不是100)。
下边代码:
/*
*用多线程实现一次拷贝4个文件
*输入时输入需要拷贝的文件路径及文件名(包括扩展名,否则无法判断文件类型)
* 对于拷贝后生产的新文件也需要输入文件路径及文件名
* 例如输入(输入和输出路径根据个人需要更改,拷贝的路径可以不在同一父路径下):
* 需要复制的文件路径:/home/fr/test.txt
* 目标路径及文件名称:/home/fr/a.txt
* 需要复制的文件路径:/home/fr/test.txt
* 目标路径及文件名称:/home/fr/b.txt
* 需要复制的文件路径:/home/fr/test.txt
* 目标路径及文件名称:/home/fr/c.txt
* 需要复制的文件路径:/home/fr/test.txt
* 目标路径及文件名称:/home/fr/d.txt
* 输出:
* 本次复制用时:21毫秒
* 本次复制用时:21毫秒
* 本次复制用时:22毫秒
* 本次复制用时:20毫秒
*/
package b;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
import javax.swing.*;
public class Test7 extends JFrame{
private static final long serialVersionUID=1L;
public static String [] s1=new String [10];//存储原始路径
public static String [] s2=new String [10];//存储拷贝路径
// private Thread a;
// private Thread b;
// private Thread c;
// private Thread d;
private Thread [] a1=new Thread [10];//实例化一个线程数组
// private final JProgressBar[] Bar=new JProgressBar[10];
public Test7(){
getContentPane().setLayout(new GridLayout(4,1));//4行1列显示,如需修改更改参数即可
// 该注释段是一次复制一个文件的完整代码,根据具体需要可以适当增加
// ps:本来是想用数组+循环实现,但是创建进度条是临时看的,创建进度条数组每次调用都是空指针,
// 没找到解决方案
// final JProgressBar Bar1=new JProgressBar();//创建进度条
// getContentPane().add(Bar1);//添加进度条
// Bar1.setStringPainted(true);//设置进度条显示数字字符
// a1[0] = new Thread(new Test3(Bar1,s2[0]));//启动线程
// setPriority("a",5,a1[0]);
final JProgressBar Bar1=new JProgressBar();
final JProgressBar Bar2=new JProgressBar();
final JProgressBar Bar3=new JProgressBar();
final JProgressBar Bar4=new JProgressBar();
getContentPane().add(Bar1);
getContentPane().add(Bar2);
getContentPane().add(Bar3);
getContentPane().add(Bar4);
Bar1.setStringPainted(true);
Bar2.setStringPainted(true);
Bar3.setStringPainted(true);
Bar4.setStringPainted(true);
a1[0] = new Thread(new Test3(Bar1,s2[0]));
a1[1] = new Thread(new Test3(Bar2,s2[1]));
a1[2] = new Thread(new Test3(Bar3,s2[2]));
a1[3] = new Thread(new Test3(Bar4,s2[3]));
setPriority("a",5,a1[0]);
setPriority("b",5,a1[1]);
setPriority("c",5,a1[2]);
setPriority("d",5,a1[3]);
}
public static void setPriority(String str,int p,Thread t)
{
// t.setPriority(p);//设置优先级
t.setName(str);
t.start();
}
public static void Input()//输入复制路径
{
Scanner sc=new Scanner(System.in);
// System.out.print("复制文件数量:");
// int n=sc.nextInt();
// s2[0]=sc.nextLine();
for(int i=0;i<4;i++)
{
System.out.print("需要复制的文件路径:");
s1[i]=sc.nextLine();
System.out.print("目标路径及文件名称:");
s2[i]=sc.nextLine();
}
}
public static void main(String[] args) {//主函数
Input();
init(new Test7(),100,100);
}
public static void init(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
private class Test3 implements Runnable{
private final JProgressBar bar;
private final String Next;
int count=0;
private Test3 (JProgressBar bar,String Next){
this.bar=bar;
this.Next=Next;
}
public void run(){//进程中的run()方法
try {
Entry();
} catch (IOException e) {
e.printStackTrace();
}
}
public void Entry() throws IOException{//传输时间计算
// SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// System.out.println(df.format(new Date()));
long begin=System.currentTimeMillis();//记录开始时间
String str1;
String str2;
str1=s1[kmp(Next)];
str2=Next;
cp(str1,str2);//调用IO流拷贝函数
long end=System.currentTimeMillis();//计录结束时间
System.out.println("本次复制用时:"+(end-begin)+"毫秒");//输出拷贝用时
}
//IO流进行拷贝
public void cp(String str1, String str2) throws IOException {
BufferedInputStream i = new BufferedInputStream(new FileInputStream(
str1));//读取
BufferedOutputStream o = new BufferedOutputStream(new FileOutputStream(
str2));//输出
File Fi1=new File(str1);
File Fi2=new File(str2);
long file=Fi1.length();
long copyfile;
// byte[] by =new byte [1024];//注释的该段是用字节数数组进行传输的,如果传输文件比较大,建议使用该方法
// int b = 0;
// while ((b = i.read(by)) != -1) {
// copyfile=Fi2.length();
// bar.setValue(count=(int)Percent(copyfile,file));
// o.write(by);
// }
// bar.setValue(count=100);
int b = 0; //字节拷贝文件
while ((b = i.read()) != -1) {
copyfile=Fi2.length();//计算副本文件大小,用于计算拷贝进度
bar.setValue(count=Percent(copyfile,file));//进度条显示拷贝进度
o.write(b);//往指定目录文件输出
}
bar.setValue(count=100);//拷贝完成将进度条更新为100%
i.close();//关闭流
o.close();//关闭流
return;
}
public int kmp(String str){//拷贝时用与查找对应文件的路径
for(int i=0;i<s2.length;i++)
{
if(str.equals(s2[i]))
{
return i;
}
}
return 0;
}
public int Percent(long a , long b)//进度条显示数字计算
{
double percent=(double)a/(double)b*100;//将进度条数字转换为百分数
return (int)percent;//因为近度条显示数值为int类型,需要强制转换一下
}
}
}