gov.nih.nci.ncicb.tcga.dcc.common.util.FileUtil.java Source code

Java tutorial

Introduction

Here is the source code for gov.nih.nci.ncicb.tcga.dcc.common.util.FileUtil.java

Source

/*
 * Software License, Version 1.0 Copyright 2010 SRA International, Inc.
 * Copyright Notice.  The software subject to this notice and license includes both human
 * readable source code form and machine readable, binary, object code form (the "caBIG
 * Software").
 *
 * Please refer to the complete License text for full details at the root of the project.
 */

package gov.nih.nci.ncicb.tcga.dcc.common.util;

import gov.nih.nci.ncicb.tcga.dcc.ConstantValues;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;
import org.apache.tools.tar.TarOutputStream;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * Provides helper methods for <code>File</code> objects
 *
 * @author Julien Baboud
 *         Last updated by: $Author$
 * @version $Rev$
 */

public class FileUtil {
    private static final Log logger = LogFactory.getLog(FileUtil.class);
    private static final int BUFFER_SIZE = 1024;
    public static final String TAR = ".tar";
    public static final String TAR_GZ = ".tar.gz";
    public static final String MD5 = ".md5";

    //This way of copying is optimized and use zero-copy nio mechanism.
    //Please use when copying big files.
    public static boolean copyFile(final String sourceFilename, final String destFilename) {
        boolean success = false;
        FileChannel source = null;
        FileChannel destination = null;
        FileInputStream sourceStream = null;
        FileOutputStream destinationStream = null;
        final File destFile = new File(destFilename);
        final File sourceFile = new File(sourceFilename);
        try {
            final long size = sourceFile.length();
            sourceStream = new FileInputStream(sourceFile);
            destinationStream = new FileOutputStream(destFile);
            source = sourceStream.getChannel();
            destination = destinationStream.getChannel();
            long toTransfer = size;
            while (toTransfer > 0) {
                toTransfer -= source.transferTo(size - toTransfer, toTransfer, destination);
            }
            success = true;
        } catch (IOException iox) {
            try {
                logger.error(
                        "Unable to copy " + sourceFile.getCanonicalPath() + " to " + destFile.getCanonicalPath(),
                        iox);
            } catch (IOException iox2) {
                logger.error("Unable to copy " + sourceFile.getName() + " OR get the canonical name", iox2);
            }
        } finally {
            try {
                if (source != null) {
                    source.close();
                    source = null;
                }
                if (destination != null) {
                    destination.close();
                    destination = null;
                }
                if (sourceStream != null) {
                    sourceStream.close();
                    sourceStream = null;
                }
                if (destinationStream != null) {
                    destinationStream.close();
                    destinationStream = null;
                }
            } catch (IOException iox3) {
                logger.error("Unable to close stream?!?", iox3);
            }
        }
        return success;
    }

    /**
     * Returns the file content as String
     *
     * @param file                         the file which content is to return
     * @param normalizeToUnixLineSeparator <code>true</code> if the file content returned should have its line separators normalized to Unix standard, <code>false</code> otherwise
     * @return the file content as a String
     * @throws IOException
     */
    public static String readFile(final File file, final boolean normalizeToUnixLineSeparator) throws IOException {

        String result;

        final StringBuilder stringBuilder = new StringBuilder();
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new FileReader(file));
            final char[] buffer = new char[BUFFER_SIZE];
            int character;

            while ((character = reader.read(buffer)) != -1) {
                stringBuilder.append(buffer, 0, character);
            }
        } finally {

            if (reader != null) {
                reader.close();
            }
        }

        result = stringBuilder.toString();

        if (normalizeToUnixLineSeparator) {
            result = replaceLineSeparators(result);
        }

        return result;
    }

    /**
     * Normalize line separator to Unix standard ("\n")
     *
     * @param input the String to normalize
     * @return the input with normalized new lines
     */
    public static String replaceLineSeparators(String input) {

        // Replace "\r\n" (Windows format) with "\n" (Unix format)
        input = input.replaceAll("\r\n", "\n");

        // Replace "\r" (Mac format) with "\n" (Unix format)
        input = input.replaceAll("\r", "\n");

        return input;
    }

    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (String child : children) {
                boolean success = deleteDir(new File(dir, child));
                if (!success) {
                    return false;
                }
            }
        }

        // The directory is now empty so delete it
        return dir.delete();
    }

    public static Properties getProperties(final String filePath, final String fileName) throws IOException {

        Properties properties = new Properties();
        FileInputStream fileInputStream = null;

        try {
            //noinspection IOResourceOpenedButNotSafelyClosed
            fileInputStream = new FileInputStream(new File(filePath, fileName));
            properties.load(fileInputStream);
        } finally {
            IOUtils.closeQuietly(fileInputStream);
        }

        return properties;
    }

    /**
     * Formats file size provided in bytes properly into Kilobytes, Megabytes and Gigabytes
     *
     * @param size size in bytes
     * @return formatted size
     */
    public static String getFormattedFileSize(final long size) {
        String estimate;
        float d;
        if (size < 1048576F) {
            d = size / 1024F;
            estimate = Math.round(d * 1000F) / 1000F + " KiB";
        } else if (size < 1073741824F) {
            d = size / 1048576F;
            estimate = Math.round(d * 1000F) / 1000F + " MiB";
        } else {
            d = size / 1073741824F;
            estimate = Math.round(d * 1000F) / 1000F + " GiB";
        }
        return estimate;
    }

    /**
     * Formats file size provided in bytes properly into Kilobytes, Megabytes and Gigabytes
     *
     * @param file File
     * @return formatted size
     */
    public static String getFormattedFileSize(final File file) {
        return getFormattedFileSize(file.length());
    }

    /**
     * Writes the given content in the given file
     *
     * @param content the content to add
     * @param file    the file into which to write the content
     * @throws IOException
     */
    public static void writeContentToFile(final String content, final File file) throws IOException {

        FileWriter fileWriter = null;

        try {
            fileWriter = new FileWriter(file);
            fileWriter.write(content);

        } finally {

            if (fileWriter != null) {

                fileWriter.flush();
                fileWriter.close();
            }
        }
    }

    public static void copy(final String sourceFilename, final String destFilename) throws IOException {

        FileInputStream sourceFileInputStream = null;
        FileChannel sourceChannel = null;
        FileOutputStream destFileOutputStream = null;
        FileChannel destChannel = null;

        try {
            File destFile = new File(destFilename);
            final File sourceFile = new File(sourceFilename);
            if (destFile.isDirectory()) {
                // use original file's name
                destFile = new File(destFile, sourceFile.getName());
            }

            //noinspection IOResourceOpenedButNotSafelyClosed
            sourceFileInputStream = new FileInputStream(sourceFile);
            //noinspection ChannelOpenedButNotSafelyClosed
            sourceChannel = (sourceFileInputStream).getChannel();

            //noinspection IOResourceOpenedButNotSafelyClosed
            destFileOutputStream = new FileOutputStream(destFile);
            //noinspection ChannelOpenedButNotSafelyClosed
            destChannel = (destFileOutputStream).getChannel();

            final long size = sourceFile.length();
            long toTransfer = size;
            while (toTransfer > 0) {
                toTransfer -= sourceChannel.transferTo(size - toTransfer, toTransfer, destChannel);
            }

        } finally {
            IOUtils.closeQuietly(sourceFileInputStream);
            IOUtils.closeQuietly(sourceChannel);
            IOUtils.closeQuietly(destFileOutputStream);
            IOUtils.closeQuietly(destChannel);
        }
    }

    public static void move(final String sourceFilename, final String destFilename) throws IOException {

        copy(sourceFilename, destFilename);
        File sourceFile = new File(sourceFilename);
        if (!sourceFile.delete()) {
            logger.info("Failed to delete " + sourceFile);
        }
    }

    public static File makeDir(final String dirPath) {
        final File directory = new File(dirPath);
        // remove dir if already exists
        if (directory.exists()) {
            deleteDir(directory);
        }
        // create dir
        directory.mkdir();
        return directory;

    }

    public static String getFilenameWithoutExtension(final String filename, final String extension)
            throws IOException {
        final File file = new File(filename);
        return file.getCanonicalPath().substring(file.getCanonicalPath().lastIndexOf(File.separator) + 1,
                file.getCanonicalPath().lastIndexOf(extension));
    }

    /**
     * Expands a tar or tar.gz archive into the given directory
     *
     * @param expandDir the target directory
     * @param tarOrTarGzFilename the name of the archive to expand (must be tar or tar.gz)
     * @throws IOException
     */
    public static void explodeTarOrTarGz(final File expandDir, final String tarOrTarGzFilename) throws IOException {

        final File file = new File(tarOrTarGzFilename);
        final FileInputStream fStream = new FileInputStream(file);

        String filenameWithoutExtension;
        if (tarOrTarGzFilename.endsWith(ConstantValues.COMPRESSED_ARCHIVE_EXTENSION)) {
            filenameWithoutExtension = getFilenameWithoutExtension(tarOrTarGzFilename,
                    ConstantValues.COMPRESSED_ARCHIVE_EXTENSION);
        } else {
            filenameWithoutExtension = getFilenameWithoutExtension(tarOrTarGzFilename,
                    ConstantValues.UNCOMPRESSED_ARCHIVE_EXTENSION);
        }

        GZIPInputStream gzipStream = null;
        TarInputStream tin = null;
        TarEntry tarEntry;
        final StringBuffer errorMsg = new StringBuffer();
        try {
            //noinspection IOResourceOpenedButNotSafelyClosed

            if (tarOrTarGzFilename.endsWith(ConstantValues.COMPRESSED_ARCHIVE_EXTENSION)) {
                gzipStream = new GZIPInputStream(fStream);
                tin = new TarInputStream(gzipStream);
            } else {
                tin = new TarInputStream(fStream);
            }

            while ((tarEntry = tin.getNextEntry()) != null) {
                String entryName = tarEntry.getName();
                final File entryFile = new File(entryName);

                if (!tarEntry.isDirectory()) {
                    if (!entryName.startsWith(filenameWithoutExtension)) {
                        errorMsg.append(
                                "Archive files should be contained inside a single directory with the same name as the archive.\n");
                    }

                    // extract out just the filename of the entry
                    if (entryFile.getCanonicalPath().lastIndexOf(File.separator) != -1) {
                        entryName = entryFile.getCanonicalPath()
                                .substring(entryFile.getCanonicalPath().lastIndexOf(File.separator));
                    }
                    final File destPath = new File(expandDir, entryName);
                    FileOutputStream fout = new FileOutputStream(destPath);
                    try {
                        tin.copyEntryContents(fout);
                    } finally {
                        fout.flush();
                        fout.close();
                        fout = null;
                    }
                } else {
                    if (!entryName.equals(filenameWithoutExtension)
                            && !entryName.equals(filenameWithoutExtension + File.separator)
                            && !entryName.equals(filenameWithoutExtension + "/")) {

                        String t = filenameWithoutExtension + File.separator;
                        errorMsg.append("Archive contains a non-standard directory '").append(entryName).append(
                                "'.  Archive files should be contained inside a single directory with the same name as the archive.\n");
                    }
                }
            }
        } finally {
            IOUtils.closeQuietly(tin);
            IOUtils.closeQuietly(gzipStream);
            IOUtils.closeQuietly(fStream);
            if (errorMsg.length() > 0)
                throw new IOException(errorMsg.toString());
        }
    }

    /**
     * Creates compressed file for the given file
     *
     * @param fileNameToBeCompressed File to be compressed path name
     * @param compressedFileName     Compressed file path name
     * @throws IOException
     */
    public static void createCompressedFile(final String fileNameToBeCompressed, final String compressedFileName)
            throws IOException {
        final List<String> fileNamesList = new ArrayList();
        fileNamesList.add(fileNameToBeCompressed);
        createCompressedFiles(fileNamesList, compressedFileName);
    }

    public static void createCompressedFiles(final List<String> fileNamesToBeCompressed,
            final String compressedFileName) throws IOException {

        final File compressedFile = new File(compressedFileName);
        for (final String fileNameToBeCompressed : fileNamesToBeCompressed) {
            final File fileToBeCompressed = new File(fileNameToBeCompressed);

            if (!fileToBeCompressed.exists()) {
                throw new IOException("Cache File does not exist: " + fileToBeCompressed.getPath());
            }
        }
        final FileOutputStream outputFileStream = new FileOutputStream(compressedFile);
        final TarOutputStream tarStream = new TarOutputStream(new GZIPOutputStream(outputFileStream));
        try {
            for (final String fileNameToBeCompressed : fileNamesToBeCompressed) {
                final File fileToBeCompressed = new File(fileNameToBeCompressed);
                final String name = fileToBeCompressed.getName();
                final TarEntry tarAdd = new TarEntry(fileToBeCompressed);

                tarStream.setLongFileMode(TarOutputStream.LONGFILE_GNU);
                tarAdd.setModTime(fileToBeCompressed.lastModified());
                tarAdd.setName(name);
                tarStream.putNextEntry(tarAdd);

                FileInputStream inputStream = null;
                byte[] buffer = new byte[1024 * 64];
                try {

                    inputStream = new FileInputStream(fileToBeCompressed);
                    int nRead = inputStream.read(buffer, 0, buffer.length);
                    while (nRead >= 0) {
                        tarStream.write(buffer, 0, nRead);
                        nRead = inputStream.read(buffer, 0, buffer.length);
                    }

                    tarStream.closeEntry();
                } finally {
                    buffer = null;
                    try {
                        if (inputStream != null) {
                            inputStream.close();
                        }
                    } catch (IOException ie) {
                        logger.error("Error closing I/O streams " + ie.toString());
                    }
                }

            }
        } finally {
            if (tarStream != null) {
                tarStream.close();
            }

        }
    }
}