com.complexible.common.io.Files2.java Source code

Java tutorial

Introduction

Here is the source code for com.complexible.common.io.Files2.java

Source

/*
 * Copyright (c) 2005-2013 Clark & Parsia, LLC. <http://www.clarkparsia.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.complexible.common.io;

import com.complexible.common.base.Dates;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import com.google.common.io.Files;
import com.google.common.io.Closeables;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileFilter;

import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;

import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>Collection of utility functions for file-centric operations.</p>
 *
 * @author  Michael Grove
 * @since   1.0
 * @version 2.2
 */
public final class Files2 {

    private Files2() {
        throw new AssertionError();
    }

    public static String path(final String theSegment, final String... theSegments) {
        return Joiner.on(File.pathSeparatorChar).skipNulls().join(null, theSegment, (String[]) theSegments);
    }

    /**
     * Create a valid directory from the given {@link File}
     * @param theDirectory the directory to create
     * @throws IOException if the directory cannot be created
     * @return the newly created directory
     */
    public static File createDirectory(File theDirectory) throws IOException {

        if (theDirectory.exists()) {
            if (!theDirectory.isDirectory()) {
                deleteRecursively(theDirectory);
            }
        } else {
            if (!theDirectory.mkdirs()) {
                throw new IOException("Unable to create directory " + theDirectory);
            }
        }

        return theDirectory;
    }

    /**
     * <p>Recursively deletes a directory and <b>all</b> its contents, if this a file, it will simply be deleted.</p>
     *
     * <p>Be careful calling this, if any directory is a symlink, this could delete the contents of the linked directory.</p>
     *
     * @param theFile      the file or directory to recursively delete.
     *
     * @throws IOException   if there was an error while deleting
     */
    public static void deleteRecursively(final File theFile) throws IOException {
        Preconditions.checkNotNull(theFile);

        if (theFile.isDirectory()) {
            // shaky symlink detection, picked up from Guava
            if (theFile.getCanonicalPath().equals(theFile.getAbsolutePath())) {
                final File[] aFiles = theFile.listFiles();
                if (aFiles == null) {
                    throw new IOException("Error listing files for " + theFile);
                }
                for (File aFile : aFiles) {
                    deleteRecursively(aFile);
                }
            }
        }

        if (!theFile.delete()) {
            throw new IOException("Failed to delete file: " + theFile);
        }
    }

    /**
     * Recursively traverse the directory and all its sub directories and return a list of all the files contained within.
     * @param theDirectory the start directory
     * @return all files in the start directory and all its sub directories.
     */
    public static List<File> listFiles(File theDirectory) {
        return listFiles(theDirectory, new FileFilter() {
            public boolean accept(File theFile) {
                // an accept all file filter
                return true;
            }
        });
    }

    /**
     * Zip the given directory.
     * @param theDir the directory to zip
     * @param theOutputFile the zip file to write to
     * @throws IOException thrown if there is an error while zipping the directory or while saving the results.
     */
    public static void zipDirectory(File theDir, File theOutputFile) throws IOException {
        ZipOutputStream aZipOut = new ZipOutputStream(new FileOutputStream(theOutputFile));

        try {
            Collection<File> aFileList = listFiles(theDir);

            String aPathToRemove = theDir.getAbsolutePath().substring(0,
                    theDir.getAbsolutePath().lastIndexOf(File.separator));

            for (File aFile : aFileList) {
                FileInputStream aFileIn = new FileInputStream(aFile);

                try {
                    ZipEntry aZipEntry = new ZipEntry(aFile.getAbsolutePath().substring(
                            aFile.getAbsolutePath().indexOf(aPathToRemove) + aPathToRemove.length() + 1));

                    aZipOut.putNextEntry(aZipEntry);

                    ByteStreams.copy(aFileIn, aZipOut);
                } finally {
                    aZipOut.closeEntry();
                    Closeables.close(aFileIn, false);
                }
            }
        } finally {
            Closeables.close(aZipOut, false);
        }
    }

    /**
     * Recursively traverse the directory and all its sub directories and return a list of all the files contained within.
     * Only files which match the file filter will be returned.
     * @param theDirectory the start directory
     * @param theFilter the file filter to use.
     * @return the list of files in the directory (and its sub directories) which match the file filter.
     */
    public static List<File> listFiles(File theDirectory, FileFilter theFilter) {

        ArrayList<File> aList = new ArrayList<File>();

        if (!theDirectory.isDirectory()) {
            return aList;
        }

        File[] aFileList = theDirectory.listFiles();

        if (aFileList == null) {
            return aList;
        }

        for (File aFile : aFileList) {
            if (aFile.isDirectory()) {
                aList.addAll(listFiles(aFile, theFilter));
            } else if (theFilter.accept(aFile)) {
                aList.add(aFile);
            }
        }

        return aList;
    }

    /**
     * Rotates a file.  Moves the specified file to a new file in the same directory, the name of the
     * new file is postfixed with the current date (YYYY-mm-dd).  If this file exists, that file name
     * is post-fixed .<num> where number is continuously incremented counter until a unique file
     * name is found.
     *
     * @param theFile       the file name to be rotated
     *
     * @throws IOException  if the file could not be moved to the new location
     */
    public static void rotate(final File theFile) throws IOException {
        final String aDate = Dates.date(new Date(theFile.lastModified()));

        File aLogBk = new File(theFile.getParent(), theFile.getName() + "." + aDate);
        int aCount = 0;
        while (aLogBk.exists()) {
            aLogBk = new File(theFile.getParent(), theFile.getName() + "." + aDate + "." + aCount++);
        }

        Files.move(theFile, aLogBk);
    }

    public static void copyDirectory(final File theSource, final File theDest) throws IOException {

        if (theSource.isDirectory()) {
            if (!theDest.exists()) {
                if (!theDest.mkdir()) {
                    throw new IOException("Could not create destination");
                }
            }

            String[] aChildren = theSource.list();
            for (String aChild : aChildren) {
                copyDirectory(new File(theSource, aChild), new File(theDest, aChild));
            }
        } else {
            Closer aCloser = Closer.create();

            InputStream in = new FileInputStream(theSource);
            OutputStream out = new FileOutputStream(theDest);

            aCloser.register(in);
            aCloser.register(out);

            ByteStreams.copy(in, out);

            aCloser.close();
        }
    }

    public static boolean deleteFiles(final File theFile) {
        Preconditions.checkNotNull(theFile);

        boolean aResult = true;

        if (theFile.isDirectory()) {
            for (File file : theFile.listFiles()) {
                if (file.isFile()) {
                    aResult = aResult && file.delete();
                }
            }
        }

        return aResult;
    }
}