使用Java复制文件时的进度条 [英] Progress bar while copying files with Java

查看:263
本文介绍了使用Java复制文件时的进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确定这个问题之前已经问过,但是我发现的答案都不能很好地与我现有的代码。我发布这个问题,万一有一个方法来做,而不完全重做我到目前为止。



这个想法是显示一个非常基本的进度条,同时复制文件和目录从一个驱动器到另一个。我有一个名为BasicCopy的类,旨在将图片,文档,视频和音乐文件夹(Windows机器上的标准文件)的内容复制到第二个驱动器上的备份目录中的相同名称的文件夹。这是到目前为止的类:

  import java.io.File; 
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.io.FileUtils;

public class BasicCopy {

String username =;
String mainDrive =;
String backupDrive =;
String backupDir =;
String []目录;

public BasicCopy(String inDrive,String outDrive,String username){
mainDrive = inDrive;
backupDrive = outDrive;
this.username = username;

createBackupDirectory();
copyDirectories();

close();
}

//创建备份目录
public void createBackupDirectory(){
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(MM-dd-yyyy_HMMSS);
String timestamp = sdf.format(date);
backupDir = backupDrive +:\\+备份+时间戳;
文件backupDirectory =新文件(backupDir);
backupDirectory.mkdir();
}

public void copyDirectories(){
//主目录
String pics = mainDrive +:\\Users\\+ username +\\Pictures;
String docs = mainDrive +:\\Users\\+ username +\\Documents;
String vids = mainDrive +:\\Users\\+ username +\\Videos;
String musc = mainDrive +:\\Users\\+ username +\\Music;
//备份目录
String bkPics = backupDir +\\Pictures;
String bkDocs = backupDir +\\Documents;
String bkVids = backupDir +\\Documents;
String bkMusc = backupDir +\\Pictures;

String [] directories = {pics,docs,vids,musc};
String [] bkDirectories = {bkPics,bkDocs,bkVids,bkMusc};

//循环遍历目录和复制文件
for(int i = 0; i 文件src = new File(directories [i ]);
文件dest =新文件(bkDirectories [i]);
try {
FileUtils.copyDirectory(src,dest);
} catch(IOException e){
e.printStackTrace();
}
}
}

/ *关闭当前进程* /
public void close(){
System.exit(0) ;
}
}



我在前一个类中有一个方法,目录的总大小,所以我可以传递到这个类如果必要。然而,我目前只循环通过四个目录,所以我希望我不能增加一个进度条,任何更高的分辨率,每分钟25%。我想知道是否有一个方法,我可能会改变它,以便我可以包括一个进度条来监视它,并有一个更准确的一点?此外,我不知道这是否应该在不同的线程或不是,但这种文件复制的方法需要很长的时间。复制500MB的文件需要几个小时,我想知道是否可能有办法加快速度?这部分不是一个优先事项。现在我主要有兴趣在进度条中添加。干杯!



编辑:



代码类似这里(这个确切的代码可能或可能不工作 - 我只是记下它很快,所以我不会忘记它,它仍然是未经测试的)。这将允许我更新每个复制的文件的进度条。

  for(int i = 0; i< directories.length; i ++){
File dir = new File (目录[i]);
文件dest =新文件(bkDirectories [i]);
for(文件file:dir.listFiles()){
try {
FileUtils.copyDirectory(file,dest);
//在这里更新进度条
} catch(IOException e){
e.printStackTrace();
}
}
}



我已经在代码上工作了一些,我相信我已经想出了大部分。现在的问题是关于一个SwingWorker,我相信我需要为了在后台运行长期方法。否则GUI变得无响应(在Java文档中有很多关于此的文档)。然而,这是我被困住的地方。我之前只使用了一个SwingWorker,主要是复制代码。我想知道如何使用下面的代码实现,以便进度条(和框架的其余部分)实际出现。



更新的代码:

  import java.awt.Toolkit; 
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JProgressBar;
import javax.swing.JLabel;

import org.apache.commons.io.FileUtils;

@SuppressWarnings(serial)
public class BasicCopy extends JFrame {

private JPanel contentPane;
private JTextArea txtCopiedDirs;
private JButton btnCancel;
private JProgressBar progressBar;
private JLabel lblCopying;
private String mainDrive;
private String backupDrive;
private String username;
private String backupDir;
long totalSize = 0; //目录/文件的总大小
long currentSize = 0; //当前文件大小计数到ONE_PERCENT
int currentPercent = 0; // current progress in%
long ONE_PERCENT; // totalSize / 100

public BasicCopy(){
}

public BasicCopy(String inDrive,String outDrive,String username,long space){
mainDrive = inDrive;
backupDrive = outDrive;
this.username = username;
totalSize = space;
ONE_PERCENT = totalSize / 100;
createGUI();

/ *这里不应该有这些!
*确定我需要一个SwingWorker
* /
createBackupDirectory();
copyDirectories();
}

public void createGUI(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(备份进度);
setBounds(100,100,450,300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5,5,5,5));
setContentPane(contentPane);
contentPane.setLayout(null);

txtCopiedDirs = new JTextArea();
txtCopiedDirs.setBounds(10,56,414,125);
contentPane.add(txtCopiedDirs);

btnCancel = new JButton(Cancel);
btnCancel.setBounds(169,227,89,23);
contentPane.add(btnCancel);

progressBar = new JProgressBar(0,100);
progressBar.setBounds(10,192,414,24);
progressBar.setValue(0);
contentPane.add(progressBar);

lblCopying = new JLabel(现在备份文件...);
lblCopying.setBounds(10,11,157,34);
contentPane.add(lblCopying);

setVisible(true);
}

//创建备份目录
public void createBackupDirectory(){
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(MM-dd-yyyy_HMMSS);
String timestamp = sdf.format(date);
backupDir = backupDrive +:\\+备份+时间戳;
文件backupDirectory =新文件(backupDir);
backupDirectory.mkdir();
}

public void copyDirectories(){
//主目录
String pics = mainDrive +:\\Users\\+ username +\\Pictures;
String docs = mainDrive +:\\Users\\+ username +\\Documents;
String vids = mainDrive +:\\Users\\+ username +\\Videos;
String musc = mainDrive +:\\Users\\+ username +\\Music;
//备份目录
String bkPics = backupDir +\\Pictures;
String bkDocs = backupDir +\\Documents;
String bkVids = backupDir +\\Documents;
String bkMusc = backupDir +\\Pictures;

String [] directories = {pics,docs,vids,musc};
String [] bkDirectories = {bkPics,bkDocs,bkVids,bkMusc};

//循环遍历目录和复制文件
for(int i = 0; i 文件dir = new File(directories [i ]);
文件dest =新文件(bkDirectories [i]);
for(文件file:dir.listFiles()){
try {
FileUtils.copyDirectory(file,dest);
if(getDirSize(file)> = ONE_PERCENT){
currentPercent ++;
progressBar.setValue(currentPercent);
currentSize = 0;
} else {
currentSize = currentSize + getDirSize(file);
if(currentSize> = ONE_PERCENT){
currentPercent ++;
progressBar.setValue(currentPercent);
currentSize = 0;
}
}
} catch(IOException e){
e.printStackTrace();
}
}
}
}

public static Long getDirSize(文件目录){
long size = 0L;

if(directory.listFiles()!= null){
for(文件file:directory.listFiles()){
size + = file.isDirectory getDirSize(file):file.length();
}
}
return size;
}

/ *关闭当前窗口* /
public void closeWindow(){
WindowEvent close = new WindowEvent(this,WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit()。getSystemEventQueue()。postEvent(close);
System.exit(0);
}
}


解决方案

I找到了一个解决方案。它仍然有一些小的毛刺,但主要是不重要的细节。

  class Task扩展SwingWorker< Void,Void> {
@Override
public Void doInBackground(){
setProgress(0);

//创建备份目录
日期date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(MM-dd-yyyy_HMMSS);
String timestamp = sdf.format(date);
backupDir = backupDrive +:\\+Backup_+ timestamp;
文件backupDirectory =新文件(backupDir);
backupDirectory.mkdir();

//复制文件
//主目录
String pics = mainDrive +:\\Users\\+ username +\\Pictures \\;
String docs = mainDrive +:\\Users\\+ username +\\Documents\\;
String vids = mainDrive +:\\Users\\+ username +\\Videos\\;
String musc = mainDrive +:\\Users\\+ username +\\Music\\;
//备份目录
String bkPics = backupDir +\\Pictures\\;
String bkDocs = backupDir +\\Documents\\;
String bkVids = backupDir +\\Documents\\;
String bkMusc = backupDir +\\Pictures\\;

String [] directories = {pics,docs,vids,musc};
String [] bkDirectories = {bkPics,bkDocs,bkVids,bkMusc};

//循环遍历目录和复制文件
for(int i = 0; i 文件dir = new File(directories [i ]);
文件dest =新文件(bkDirectories [i]);
(文件:dir.listFiles()){
try {
if(file.isFile()){
FileUtils.copyFileToDirectory(file,dest);
txtCopiedDirs.append(file.getAbsolutePath()+\\\
);
} else if(file.isDirectory()){
FileUtils.copyDirectoryToDirectory(file,dest);
txtCopiedDirs.append(file.getAbsolutePath()+\\\
);
}
if(getDirSize(file)> = ONE_PERCENT){
currentPercent = getDirSize(file)/ ONE_PERCENT;
progressBar.setValue((int)currentPercent);
currentSize = 0;
} else {
currentSize = currentSize + getDirSize(file);
if(currentSize> = ONE_PERCENT){
currentPercent = currentSize / ONE_PERCENT;
currentPercent ++;
progressBar.setValue((int)currentPercent);
currentSize = 0;
}
}
} catch(IOException e){
e.printStackTrace();
}
}
}

return null;
}
@Override
public void done(){
closeWindow();
}
}

此类包含在主类中,开始使用以下代码:

 任务任务=新任务
task.execute();

在框架创建后立即调用并设置为可见。



现在,正如我所说的,这还不完美。例如,在复制它之前检查它是一个文件还是一个目录,应该用递归函数来代替,以便它遍历每个单独的文件,而不是仅仅复制目录,如果它是一个完整的目录。这将允许更准确地更新进度条,并显示在文本区域中复制的单个文件,而不是文件和目录。



无论如何,我只是想发布此代码以显示什么为我工作,没有完全重做我有。我会继续努力,并发布任何重要的更新,可能有助于未来的读者。



感谢大家的回应,他们已经帮助了很多! >

I'm sure this question has been asked before, but none of the answers I found will work very well with my existing code. I'm posting this question in case there's a way to do it without completely redoing what I have so far.

The idea is to display a very basic progress bar while copying files and directories from one drive to another. I have a class called BasicCopy that is designed to copy the contents of the Pictures, Documents, videos, and Music folders (standard on Windows machines) to folders of the same names within a backup directory on a second drive. Here is the class so far:

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.io.FileUtils;

public class BasicCopy {

    String username = "";
    String mainDrive = "";
    String backupDrive = "";
    String backupDir = "";
    String[] directories;

    public BasicCopy(String inDrive, String outDrive, String username){
        mainDrive = inDrive;
        backupDrive = outDrive;
        this.username = username;

        createBackupDirectory();
        copyDirectories();

        close();
    }

    //Create backup directory
    public void createBackupDirectory(){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy_HMMSS");
        String timestamp = sdf.format(date);
        backupDir = backupDrive + ":\\" + "Backup " + timestamp;
        File backupDirectory = new File(backupDir);
        backupDirectory.mkdir();
    }

    public void copyDirectories(){
        //Main directories
        String pics = mainDrive + ":\\Users\\" + username + "\\Pictures";
        String docs = mainDrive + ":\\Users\\" + username + "\\Documents";
        String vids = mainDrive + ":\\Users\\" + username + "\\Videos";
        String musc = mainDrive + ":\\Users\\" + username + "\\Music";
        //Backup directories
        String bkPics = backupDir + "\\Pictures";
        String bkDocs = backupDir + "\\Documents";
        String bkVids = backupDir + "\\Documents";
        String bkMusc = backupDir + "\\Pictures";

        String[] directories = {pics, docs, vids, musc};
        String[] bkDirectories = {bkPics, bkDocs, bkVids, bkMusc};

        //Loop through directories and copy files
        for (int i = 0; i < directories.length; i++){
            File src = new File(directories[i]);
            File dest = new File(bkDirectories[i]);
            try{
                FileUtils.copyDirectory(src, dest);
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    /* Close current process */
    public void close(){
        System.exit(0);
    }
}

I have a method in a previous class that measures the total size of the directories, so I could pass that in to this class if necessary. However, I currently loop through only the four directories, so I expect I wouldn't be able to increment a progress bar with any higher resolution than 25% per tick. I am wondering if there's a way I might change it so that I can include a progress bar to monitor it, and have it be a little more accurate? Furthermore, I'm not sure if this should be asked in a different thread or not, but this method of file copying takes a very long time. It takes hours to copy 500MB worth of files, and I was wondering if there might be a way to speed it up? That part isn't a priority though. Right now I'm mainly interested in adding in a progress bar. Cheers!

EDIT:

After some fiddling I realized I could probably use code similar to this (This exact code may or may not work--I just jotted it down quickly so I wouldn't forget it, it is still untested). This would allow me to update the progress bar for each file copied.

for (int i = 0; i < directories.length; i++){
    File dir = new File(directories[i]);
    File dest = new File(bkDirectories[i]);
    for(File file: dir.listFiles()){
        try{
            FileUtils.copyDirectory(file, dest);
            //update progress bar here
        } catch (IOException e){
            e.printStackTrace();
        }
    }
}

EDIT #2:

I have worked a bit more on the code and I believe I've figured most of it out. The question now is about a SwingWorker, which I believe I'll need in order to run the long-term methods in the background. Otherwise the GUI becomes unresponsive (lots of documentation on this in the Java docs). However, this is where I get stuck. I've only used a SwingWorker once before, and that was mainly with copied code. I am wondering how I could implement that using the following code so that the progress bar (and the rest of the frame) actually appears.

Updated code:

import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JProgressBar;
import javax.swing.JLabel;

import org.apache.commons.io.FileUtils;

@SuppressWarnings("serial")
public class BasicCopy extends JFrame {

    private JPanel contentPane;
    private JTextArea txtCopiedDirs;
    private JButton btnCancel;
    private JProgressBar progressBar;
    private JLabel lblCopying;
    private String mainDrive;
    private String backupDrive;
    private String username;
    private String backupDir;
    long totalSize = 0; //total size of directories/files
    long currentSize = 0;   //current size of files counting up to ONE_PERCENT
    int currentPercent = 0; //current progress in %
    long ONE_PERCENT;       //totalSize / 100

    public BasicCopy() {
    }

    public BasicCopy(String inDrive, String outDrive, String username, long space){
        mainDrive = inDrive;
        backupDrive = outDrive;
        this.username = username;
        totalSize = space;
        ONE_PERCENT = totalSize/100;
        createGUI();

        /*  Should not have these here!
         *  Pretty sure I need a SwingWorker
         */
        createBackupDirectory();
        copyDirectories();
    }

    public void createGUI(){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Backup Progress");
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        txtCopiedDirs = new JTextArea();
        txtCopiedDirs.setBounds(10, 56, 414, 125);
        contentPane.add(txtCopiedDirs);

        btnCancel = new JButton("Cancel");
        btnCancel.setBounds(169, 227, 89, 23);
        contentPane.add(btnCancel);

        progressBar = new JProgressBar(0, 100);
        progressBar.setBounds(10, 192, 414, 24);
        progressBar.setValue(0);
        contentPane.add(progressBar);

        lblCopying = new JLabel("Now backing up your files....");
        lblCopying.setBounds(10, 11, 157, 34);
        contentPane.add(lblCopying);

        setVisible(true);
    }

    //Create backup directory
    public void createBackupDirectory(){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy_HMMSS");
        String timestamp = sdf.format(date);
        backupDir = backupDrive + ":\\" + "Backup " + timestamp;
        File backupDirectory = new File(backupDir);
        backupDirectory.mkdir();
    }

    public void copyDirectories(){
        //Main directories
        String pics = mainDrive + ":\\Users\\" + username + "\\Pictures";
        String docs = mainDrive + ":\\Users\\" + username + "\\Documents";
        String vids = mainDrive + ":\\Users\\" + username + "\\Videos";
        String musc = mainDrive + ":\\Users\\" + username + "\\Music";
        //Backup directories
        String bkPics = backupDir + "\\Pictures";
        String bkDocs = backupDir + "\\Documents";
        String bkVids = backupDir + "\\Documents";
        String bkMusc = backupDir + "\\Pictures";

        String[] directories = {pics, docs, vids, musc};
        String[] bkDirectories = {bkPics, bkDocs, bkVids, bkMusc};

        //Loop through directories and copy files
        for (int i = 0; i < directories.length; i++){
            File dir = new File(directories[i]);
            File dest = new File(bkDirectories[i]);
            for(File file: dir.listFiles()){
                try{
                    FileUtils.copyDirectory(file, dest);
                    if(getDirSize(file) >= ONE_PERCENT){
                        currentPercent++;
                        progressBar.setValue(currentPercent);
                        currentSize = 0;
                    } else {
                        currentSize = currentSize + getDirSize(file);
                        if(currentSize >= ONE_PERCENT){
                            currentPercent++;
                            progressBar.setValue(currentPercent);
                            currentSize = 0;
                        }
                    }
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    public static Long getDirSize(File directory) {
        long size = 0L;

        if (directory.listFiles() != null){       
            for (File file : directory.listFiles()) {
                size += file.isDirectory() ? getDirSize(file) : file.length();
            }
        }
        return size;
    }

    /* Close current window */
    public void closeWindow() {
        WindowEvent close = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
        System.exit(0);
    }
}

解决方案

I have found a solution that works. It still has some minor glitches, but mainly with unimportant details. Here is what I have now, and it seems to be working.

class Task extends SwingWorker<Void, Void>{
    @Override
    public Void doInBackground(){
        setProgress(0);

        //Create Backup Directory
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy_HMMSS");
        String timestamp = sdf.format(date);
        backupDir = backupDrive + ":\\" + "Backup_" + timestamp;
        File backupDirectory = new File(backupDir);
        backupDirectory.mkdir();

        //Copy Files
        //Main directories
        String pics = mainDrive + ":\\Users\\" + username + "\\Pictures\\";
        String docs = mainDrive + ":\\Users\\" + username + "\\Documents\\";
        String vids = mainDrive + ":\\Users\\" + username + "\\Videos\\";
        String musc = mainDrive + ":\\Users\\" + username + "\\Music\\";
        //Backup directories
        String bkPics = backupDir + "\\Pictures\\";
        String bkDocs = backupDir + "\\Documents\\";
        String bkVids = backupDir + "\\Documents\\";
        String bkMusc = backupDir + "\\Pictures\\";

        String[] directories = {pics, docs, vids, musc};
        String[] bkDirectories = {bkPics, bkDocs, bkVids, bkMusc};

        //Loop through directories and copy files
        for (int i = 0; i < directories.length; i++){
            File dir = new File(directories[i]);
            File dest = new File(bkDirectories[i]);
            for(File file: dir.listFiles()){
                try{
                    if(file.isFile()){
                        FileUtils.copyFileToDirectory(file, dest);
                        txtCopiedDirs.append(file.getAbsolutePath() + "\n");
                    } else if (file.isDirectory()){
                        FileUtils.copyDirectoryToDirectory(file, dest);
                        txtCopiedDirs.append(file.getAbsolutePath() + "\n");
                    }
                    if(getDirSize(file) >= ONE_PERCENT){
                        currentPercent = getDirSize(file)/ONE_PERCENT;
                        progressBar.setValue((int)currentPercent);
                        currentSize = 0;
                    } else {
                        currentSize = currentSize + getDirSize(file);
                        if(currentSize >= ONE_PERCENT){
                            currentPercent = currentSize/ONE_PERCENT;
                            currentPercent++;
                            progressBar.setValue((int)currentPercent);
                            currentSize = 0;
                        }
                    }
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
        }

        return null;
    }
    @Override
    public void done(){
        closeWindow();
    }
}

This class is contained within the main class, and is started using the following code:

Task task = new Task();
task.execute();

This is called immediately after the frame is created and set visible.

Now, as I mentioned this still isn't perfect. For example, the check to see if it's a file or a directory before copying it should be replaced with a recursive function, so that it loops through each individual file, rather than just copy the directory if it's a full directory. This will allow for more accurate updating of the progress bar and will show the individual files being copied in the text area, rather than files and directories.

Anyway, I just wanted to post this code to show what has worked for me, without completely redoing what I had. I will keep working on it though, and post any important updates that may help future readers.

Thanks everyone for the responses, they've helped a lot!

这篇关于使用Java复制文件时的进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆