Directory Copy

The javaxt.io.Directory class makes it easy to copy directories. Here are a few examples.

Simple Copy

In this example, we simply copy the contents of the input directory to the output directory.

javaxt.io.Directory input = new javaxt.io.Directory("/source");
javaxt.io.Directory output = new javaxt.io.Directory("/destination");
input.copyTo(output, true); //true to overwrite any existing files

Copy Specific Files Using File Filters

The Directory.copyTo() method allows users to provide an optional file filter to specify which files to copy. In the following example, we will copy only PDF files from the input directory:

        javaxt.io.Directory input = new javaxt.io.Directory("/source");
        javaxt.io.Directory output = new javaxt.io.Directory("/destination");
        input.copyTo(output, "*.pdf", true); //true to overwrite any existing files

You can also can pass in multiple wildcards using an String array. In this example, we will copy images from the input directory to the output directory:

        String[] filter = new String[]{"*.jpg", "*.png", "*.gif", "*.tif"};
        input.copyTo(output, filter, true); //true to overwrite any existing files

Of course, you can also use a standard java.io.FileFilter. Here's a simple example used to copy txt files.

    java.io.FileFilter filter = new java.io.FileFilter() {
        public boolean accept(java.io.File file) {

            if (file.isHidden()) return false;
            else{
                if (file.isDirectory()) return true;
                else return (file.getName().endsWith(".txt"));
            }
        }
    };
    input.copyTo(output, filter, true); //true to overwrite any existing files

Multi-Threaded File Copy

Under the hood, the copy method performs a multi-threaded, recursive search using the Directory.getChildren() method and copies files using the javaxt.io.File.copy() methods. File copies are performed in a single thread. You can dramatically improve copy performance using multiple threads. Here's a simple example to illustrate how this is done. In this example, we will copy any JSON files found in the input directory and copy them to the output directory.

    public static void MultiThreadedFileCopy(){

        javaxt.io.Directory input = new javaxt.io.Directory("/temp/input");
        javaxt.io.Directory output = new javaxt.io.Directory("/temp/output");
        String fileFilter = "*.json";

      //Spawn threads
        int numThreads = 4;
        java.util.ArrayList<Thread> threads = new java.util.ArrayList<Thread>();
        for (int i=0; i<numThreads; i++){
            Thread thread = new Thread(new FileCopier(input, output));
            threads.add(thread);
            thread.start();
        }


      //Initiate search
        int numFiles = 0;
        java.util.List results = input.getChildren(true, fileFilter, false);
        while (true){
            Object item;
            synchronized (results) {
                while (results.isEmpty()) {
                    try {
                        results.wait();
                    }
                    catch (InterruptedException e) {
                        break;
                    }
                }
                item = results.remove(0);
                results.notifyAll();
            }

            if (item!=null){

                if (item instanceof javaxt.io.File){

                  //Add file to the file copier
                    javaxt.io.File file = (javaxt.io.File) item;
                    FileCopier.add(file);
                    numFiles++;
                }
            }
            else{ //item is null. This is our queue that the search is done!
                break;
            }
        }


      //Notify threads that we are done adding files to the queue
        FileCopier.done();
        System.out.println("Found " + numFiles + " files to copy.");


      //Wait for threads to complete
        while (true) {
            try {
                for (Thread thread : threads){
                    thread.join();
                }
                break;
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        threads.clear();

        System.out.println("Copy complete!");

    }


  //**************************************************************************
  //** FileCopier
  //*************************************************************************/
  /** Thread used to copy files from an input directory to an output directory 
   */
    private static class FileCopier implements Runnable {

        private static java.util.List pool = new java.util.LinkedList();
        private javaxt.io.Directory output;
        private int pathLength = -1;


        public FileCopier(javaxt.io.Directory input, javaxt.io.Directory output) {
            pathLength = input.getPath().length();
            this.output = output;
        }

        public static void add(javaxt.io.File file) {
            synchronized (pool) {
               pool.add(pool.size(), file);
               pool.notify(); //pool.notifyAll();
            }
        }

        public static void done() {
            synchronized (pool) {
               pool.add(pool.size(), null);
               pool.notify(); //pool.notifyAll();
            }
        }

        public void run() {

            while (true) {

                javaxt.io.File file = null;
                synchronized (pool) {
                    while (pool.isEmpty()) {
                        try {
                            pool.wait();
                        }
                        catch (InterruptedException e) {
                            return;
                        }
                    }
                    file = (javaxt.io.File) pool.get(0);
                    if (file!=null) pool.remove(0);
                    pool.notifyAll();
                }

                if (file!=null){
                    String relPath = file.getParentDirectory().getPath().substring(pathLength);
                    javaxt.io.File outputFile = new javaxt.io.File(output + relPath + file.getName());
                    file.copyTo(outputFile, true);
                }
                else{
                    System.out.println("Done!");
                    return;
                }
            }
        }
    }