Progress bar while copying files with Java

女生的网名这么多〃 提交于 2019-12-04 23:47:00

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!

I'm assuming you want a graphical progress bar, and not a console based (tui) solution. Have you read this Swing tutorial?

EDIT: If you want one tick of your progress bar per file, you simply need to tell the progress bar constructor how many total ticks there are, something like:

progressBar = new JProgressBar(0, allFilesInAllDirectoriesLength);

and organize your for loop to work on each file, instead of looping on the directories.

Here is my idea using Java 8 and apache FileUtils (can be replaced by any other). It simply checks (in separate thread) directory size every n seconds:

FUNCTIONAL INTERFACE:

public interface DirectoryMovementStatusFeedback {
    void notifyStatus(double percentMoved, double speedInMB);
}

SERVICE:

public class FileMovementStatusUpdater {

    private long checkInterval = 2000;
    private boolean interrupted = false;

    public long getCheckInterval() {
        return checkInterval;
    }

    public void setCheckInterval(long checkInterval) {
        this.checkInterval = checkInterval;
    }

    public void monitor(File directory, long desiredSize, DirectoryMovementStatusFeedback feedback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    double percentageMoved = 0;
                    double lastCheckedSize = 0;
                    do {
                        double currentSize = directory.exists() ? FileUtils.sizeOfDirectory(directory) : 0;
                        double speed = (currentSize - lastCheckedSize) / (1024 * checkInterval);
                        lastCheckedSize = currentSize;
                        percentageMoved = 100 * currentSize / desiredSize;
                        feedback.notifyStatus(percentageMoved, speed);
                        Thread.sleep(checkInterval);
                    } while (percentageMoved < 100 && !interrupted);
                } catch (Exception e) {
                    System.err.println("Directory monitor failed. " + e.getMessage());
                }
            }
        }).start();
    }

    public void stopMonitoring() {
        this.interrupted = true;
    }

USAGE:

    FileMovementStatusUpdater dirStatus = new FileMovementStatusUpdater();
    try {
        dirStatus.monitor(destination, FileUtils.sizeOfDirectory(source), (percent, speed) -> {
            progressBar.setValue(percent);
            speedLabel.setValue(speed+" MB/s");
        });
        FileUtils.moveDirectory(source, destination);
    } catch (Exception e) {
        // something
    }
    dirStatus.stopMonitoring();

This might be more complicated and maybe stupid idea bud,Maybe it helps so i decided to post it. Use your own method to copy file ,check file size ,take 1 percent from it and each time you reach amount of bites/mb/ that represent 1 percent of that file update your progress bar

Im short on time so i will at least paste some code with comments so you get idea of what i think.

//check size of files/dir to copy,before calling method bellow
//then you coud use for loop to do all the work

//make counter of how many mb/bits you already did.

    public void copyDirectory(File sourceLocation , File targetLocation) throws IOException {
        if (sourceLocation.isDirectory()) {
            if (!targetLocation.exists()) {
                targetLocation.mkdir();
            }

            String[] children = sourceLocation.list();
            for (int i=0; i<children.length; i++) {
                copyDirectory(new File(sourceLocation, children[i]),
                        new File(targetLocation, children[i]));
            }
        } else {

            InputStream in = new FileInputStream(sourceLocation);
            OutputStream out = new FileOutputStream(targetLocation);


            // Copy the bits from instream to outstream
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
                //increment counter 
                //check if counter is above next 1% of size of your dirs

                //if you are then update progress bar by one percent
            }
            in.close();
            out.close();
        }
    }

This solution is not tested bud this is how i woud start to aproach this problem.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!