title: Progress bar while copying files with Java
body: <p>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.</p>
  
  <p>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:</p>
  
  <pre><code>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 &lt; 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);
      }
  }
  </code></pre>
  
  <p>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!</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>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. </p>
  
  <pre><code>for (int i = 0; i &lt; 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();
          }
      }
  }
  </code></pre>
  
  <p><strong>EDIT #2:</strong></p>
  
  <p>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.</p>
  
  <p>Updated code:</p>
  
  <pre><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 &lt; 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) &gt;= ONE_PERCENT){
                          currentPercent++;
                          progressBar.setValue(currentPercent);
                          currentSize = 0;
                      } else {
                          currentSize = currentSize + getDirSize(file);
                          if(currentSize &gt;= 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);
      }
  }
  </code></pre>