多线程实现IO流拷贝文件

版权声明:本文为博主原创文章,未经博主允许不得转载。 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类型,需要强制转换一下
        }
    }
}
阅读更多
换一批

没有更多推荐了,返回首页