Package ca.eandb.util.io

Source Code of ca.eandb.util.io.FileUtil

/*
* Copyright (c) 2008 Bradley W. Kimmel
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

package ca.eandb.util.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.ByteBuffer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import ca.eandb.util.UnexpectedException;

/**
* File I/O utility methods.
* @author Brad Kimmel
*/
public final class FileUtil {

  /**
   * Recursively removes all entries from a directory.
   * @param directory The directory to clear.
   * @return A value indicating whether the directory was successfully
   *     cleared.  If unsuccessful, the directory may have been partially
   *     cleared.
   */
  public static boolean clearDirectory(File directory) {
    if (directory.isDirectory()) {
      for (File file : directory.listFiles()) {
        if (!deleteRecursive(file)) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * Recursively removes a file or a directory and all its subdirectories.
   * @param file The file or directory to delete.
   * @return A value indicating whether the file directory was successfully
   *     removed.  If unsuccessful, the directory may have been partially
   *     cleared.
   */
  public static boolean deleteRecursive(File file) {
    return clearDirectory(file) && file.delete();
  }

  /**
   * Reads the contents of a file into a byte array.
   * @param file The <code>File</code> to read.
   * @return A byte array containing the file's contents.
   * @throws IOException If an error occurred while reading the file.
   */
  public static byte[] getFileContents(File file) throws IOException {
    FileInputStream stream = new FileInputStream(file);
    byte[] contents = new byte[(int) file.length()];
    stream.read(contents);
    stream.close();
    return contents;
  }

  /**
   * Writes the specified byte array to a file.
   * @param file The <code>File</code> to write.
   * @param contents The byte array to write to the file.
   * @throws IOException If the file could not be written.
   */
  public static void setFileContents(File file, byte[] contents) throws IOException {
    setFileContents(file, contents, false);
  }

  /**
   * Writes the specified byte array to a file.
   * @param file The <code>File</code> to write.
   * @param contents The byte array to write to the file.
   * @param createDirectory A value indicating whether the directory
   *     containing the file to be written should be created if it does
   *     not exist.
   * @throws IOException If the file could not be written.
   */
  public static void setFileContents(File file, byte[] contents, boolean createDirectory) throws IOException {
    if (createDirectory) {
      File directory = file.getParentFile();
      if (!directory.exists()) {
        directory.mkdirs();
      }
    }

    FileOutputStream stream = new FileOutputStream(file);
    stream.write(contents);
    stream.close();
  }

  /**
   * Writes the specified byte array to a file.
   * @param file The <code>File</code> to write.
   * @param contents The byte array to write to the file.
   * @throws IOException If the file could not be written.
   */
  public static void setFileContents(File file, ByteBuffer contents) throws IOException {
    setFileContents(file, contents, false);
  }

  /**
   * Writes the specified byte array to a file.
   * @param file The <code>File</code> to write.
   * @param contents The byte array to write to the file.
   * @param createDirectory A value indicating whether the directory
   *     containing the file to be written should be created if it does
   *     not exist.
   * @throws IOException If the file could not be written.
   */
  public static void setFileContents(File file, ByteBuffer contents, boolean createDirectory) throws IOException {
    if (createDirectory) {
      File directory = file.getParentFile();
      if (!directory.exists()) {
        directory.mkdirs();
      }
    }

    FileOutputStream stream = new FileOutputStream(file);
    StreamUtil.writeBytes(contents, stream);
    stream.close();
  }

  /**
   * Writes a single object to a file.
   * @param file The <code>File</code> to write to.
   * @param object The <code>Object</code> to write.
   * @throws IOException If the file could not be written.
   */
  public static void writeObjectToFile(File file, Object object) throws IOException {
    FileOutputStream fs = new FileOutputStream(file);
    ObjectOutputStream os = new ObjectOutputStream(fs);
    os.writeObject(object);
    os.close();
  }

  /**
   * Reads a single object from a file.
   * @param file The <code>File</code> to read from.
   * @return The <code>Object</code> read from the file.
   * @throws IOException If the file could not be read.
   * @throws ClassNotFoundException If the object's class could not be found.
   */
  public static Object readObjectFromFile(File file) throws IOException, ClassNotFoundException {
    FileInputStream fs = new FileInputStream(file);
    ObjectInputStream os = new ObjectInputStream(fs);
    Object object = os.readObject();
    os.close();
    return object;
  }

  /**
   * Determines if the specified directory is an ancestor of the specified
   * file or directory.
   * @param file The file or directory to test.
   * @param ancestor The directory for which to determine whether
   *     <code>file</code> is an ancestor.
   * @return <code>true</code> if <code>ancestor</code> is equal to or an
   *     ancestor of <code>file</code>, <code>false</code> otherwise.
   * @throws IOException
   */
  public static boolean isAncestor(File file, File ancestor) throws IOException {
    file = file.getCanonicalFile();
    ancestor = ancestor.getCanonicalFile();
    do {
      if (file.equals(ancestor)) {
        return true;
      }
      file = file.getParentFile();
    } while (file != null);
    return false;
  }

  /**
   * Removes a file or directory and its ancestors up to, but not including
   * the specified directory, until a non-empty directory is reached.
   * @param file The file or directory at which to start pruning.
   * @param root The directory at which to stop pruning.
   */
  public static void prune(File file, File root) {
    while (!file.equals(root) && file.delete()) {
      file = file.getParentFile();
    }
  }

  /**
   * Walks a directory tree using post-order traversal.  The contents of a
   * directory are visited before the directory itself is visited.
   * @param root The <code>File</code> indicating the file or directory to
   *     walk.
   * @param visitor The <code>FileVisitor</code> to use to visit files and
   *     directories while walking the tree.
   * @return A value indicating whether the tree walk was completed without
   *     {@link FileVisitor#visit(File)} ever returning false.
   * @throws Exception If {@link FileVisitor#visit(File)} threw an exception.
   * @see FileVisitor#visit(File)
   */
  public static boolean postOrderTraversal(File root, FileVisitor visitor) throws Exception {
    if (root.isDirectory()) {
      for (File child : root.listFiles()) {
        if (!postOrderTraversal(child, visitor)) {
          return false;
        }
      }
    }
    return visitor.visit(root);
  }

  /**
   * Walks a directory tree using pre-order traversal.  The contents of a
   * directory are visited after the directory itself is visited.
   * @param root The <code>File</code> indicating the file or directory to
   *     walk.
   * @param visitor The <code>FileVisitor</code> to use to visit files and
   *     directories while walking the tree.
   * @return A value indicating whether the tree walk was completed without
   *     {@link FileVisitor#visit(File)} ever returning false.
   * @throws Exception If {@link FileVisitor#visit(File)} threw an exception.
   * @see FileVisitor#visit(File)
   */
  public static boolean preOrderTraversal(File root, FileVisitor visitor) throws Exception {
    if (!visitor.visit(root)) {
      return false;
    }
    if (root.isDirectory()) {
      for (File child : root.listFiles()) {
        if (!preOrderTraversal(child, visitor)) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * Zips the contents of a directory.
   * @param zipFile The <code>File</code> indicating the zip file to create.
   * @param contents The <code>File</code> indicating the directory to zip.
   * @throws IOException If the contents could not be read or if the zip file
   *     could not be written.
   */
  public static void zip(File zipFile, final File contents) throws IOException {

    OutputStream os = new FileOutputStream(zipFile);
    final ZipOutputStream zs = new ZipOutputStream(os);

    try {
      preOrderTraversal(contents, new FileVisitor() {

        public boolean visit(File file) throws IOException {
          if (file.isFile()) {
            String name = getRelativePath(file, contents);
            zs.putNextEntry(new ZipEntry(name));

            FileInputStream fs = new FileInputStream(file);
            StreamUtil.writeStream(fs, zs);
            fs.close();

            zs.closeEntry();
          }
          return true;
        }

      });
    } catch (IOException e) {
      throw e;
    } catch (Exception e) {
      throw new UnexpectedException(e);
    }

    zs.close();

  }

  /**
   * Gets the <code>String</code> representing the path to a file relative to
   * a given directory.
   * @param file The <code>File</code> for which to obtain the relative path.
   * @param base The <code>File</code> representing the directory that the
   *     resulting path should be relative to.
   * @return The <code>String</code> representing the relative path.
   * @throws IOException If a directory along the walk from <code>base</code>
   *     to <code>file</code> could not be read.
   */
  public static String getRelativePath(File file, File base) throws IOException {
    StringWriter path = new StringWriter();

    while (!isAncestor(file, base)) {
      path.append("../");
    }

    String fileName = file.getAbsolutePath();
    String baseName = base.getAbsolutePath();
    int prefixLength = baseName.length();

    if (!baseName.endsWith("/")) {
      prefixLength++;
    }

    path.append(fileName.substring(prefixLength));

    return path.toString();
  }

  /**
     * Returns the appropriate working directory for storing application data. The result of this method is platform
     * dependant: On linux, it will return ~/applicationName, on windows, the working directory will be located in the
     * user's application data folder. For Mac OS systems, the working directory will be placed in the proper location
     * in "Library/Application Support".
     * <p/>
     * This method will also make sure that the working directory exists. When invoked, the directory and all required
     * subfolders will be created.
     *
     * @param applicationName Name of the application, used to determine the working directory.
     * @return the appropriate working directory for storing application data.
     */
  public static File getApplicationDataDirectory(final String applicationName) {
        final String userHome = System.getProperty("user.home", ".");
        final File workingDirectory;
        final String osName = System.getProperty("os.name", "").toLowerCase();
        if (osName.contains("windows")) {
          final String applicationData = System.getenv("APPDATA");
          if (applicationData != null)
              workingDirectory = new File(applicationData, applicationName + '/');
            else
              workingDirectory = new File(userHome, '.' + applicationName + '/');
        } else if (osName.contains("mac")) {
          workingDirectory = new File(userHome, "Library/Application Support/" + applicationName);
        } else {
          workingDirectory = new File(userHome, '.' + applicationName + '/');
        }
        if (!workingDirectory.exists())
            if (!workingDirectory.mkdirs())
                throw new RuntimeException("The working directory could not be created: " + workingDirectory);
        return workingDirectory;
    }

  /**
   * Gets the extension part of the specified file name.
   * @param fileName The name of the file to get the extension of.
   * @return The extension of the file name.
   */
  public static String getExtension(String fileName) {
    int pos = fileName.lastIndexOf('.');
    if (pos < 0) {
      return "";
    }
    return fileName.substring(pos + 1);
  }

  /** Declared private to prevent this class from being instantiated. */
  private FileUtil() {}

}
TOP

Related Classes of ca.eandb.util.io.FileUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.