FileUtils.java

package org.europa.together.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.HashSet;
import java.util.Set;
import org.europa.together.application.LogbackLogger;
import org.europa.together.business.Logger;
import org.europa.together.domain.ByteOrderMark;
import org.europa.together.domain.LogLevel;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Some helpful stuff for file handling.
 */
public final class FileUtils {

    private static final Logger LOGGER = new LogbackLogger(FileUtils.class);
    private static final Charset CHARSET = Charset.forName("UTF-8");

    /**
     * Constructor.
     */
    private FileUtils() {
        throw new UnsupportedOperationException();
    }

    /**
     * Convert an InputStream to an ByteArray.
     *
     * @param input as InputStream
     * @return byte[] as Array
     * @throws java.io.IOException case of error
     */
    public static byte[] inputStreamToByteArray(final InputStream input)
            throws IOException {
        byte[] byteArray = null;
        byteArray = input.readAllBytes();
        return byteArray;
    }

    /**
     * Create from an HEX repersentation integers aa byte array.
     *
     * @param ints as Hex
     * @return byte as Array
     */
    public static byte[] toBytes(final int... ints) {
        byte[] result = new byte[ints.length];
        for (int i = 0; i < ints.length; i++) {
            result[i] = (byte) ints[i];
        }
        return result;
    }

    /**
     * Write a String to a File.It is possible to create an empty file whitout
     * content. DestinationFile is a full qualitied path including the file
     * name. Sample: /home/user/file.txt
     *
     * @param content as String
     * @param destinationFile as String
     * @return true on success
     * @throws java.io.IOException case of error
     */
    public static boolean writeStringToFile(final String content, final String destinationFile)
            throws IOException {
        boolean success = false;
        LOGGER.log("writeStringToFile() destination: " + destinationFile, LogLevel.DEBUG);
        BufferedWriter writer
                = Files.newBufferedWriter(Paths.get(destinationFile), CHARSET);
        if (StringUtils.isEmpty(content)) {
            LOGGER.log("File content is empty.", LogLevel.WARN);
        } else {
            LOGGER.log("Count of characters:"
                    + content.length(), LogLevel.DEBUG);
            writer.append(content, 0, content.length());
        }
        writer.close();
        success = true;
        return success;
    }

    /**
     * Get the bytes of file. It is also possible to choose a dimension for the
     * file size. The following options for <b>dimension</b> are available:
     * kilo, mega, giga and tera.
     *
     * @param filePath as String
     * @param dimension as String
     * @return fileSize as double
     */
    public static long getFileSize(final String filePath, final String dimension) {
        String mode = "default";
        if (!StringUtils.isEmpty(dimension)) {
            mode = dimension;
        }
        File file = new File(filePath);
        long size = 0;
        if (file.exists()) {
            size = file.length();
            switch (mode) {
                default:
                    break;
                case "kilo":
                    size = size / Constraints.INT_1024;
                    break;
                case "mega":
                    size = (size / Constraints.INT_1024) / Constraints.INT_1024;
                    break;
                case "giga":
                    size = ((size / Constraints.INT_1024) / Constraints.INT_1024)
                            / Constraints.INT_1024;
                    break;
                case "tera":
                    size = (((size / Constraints.INT_1024) / Constraints.INT_1024)
                            / Constraints.INT_1024) / Constraints.INT_1024;
                    break;
            }
            LOGGER.log("Size of " + file.getName() + " is " + size + " "
                    + mode + " Bytes.", LogLevel.DEBUG);
        } else {
            LOGGER.log("File " + filePath + " does not exists!", LogLevel.ERROR);
        }
        return size;
    }

    /**
     * Read a file from the class path.
     *
     * @param path to the file
     * @return fielContent as String
     * @throws FileNotFoundException case of error
     */
    public static String readFileFromClasspath(final String path)
            throws IOException {

        StringBuilder content = new StringBuilder();
        ApplicationContext context = new ClassPathXmlApplicationContext();
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(
                        context.getResource(path).getInputStream(), "UTF8")
        );
        String line;
        while ((line = reader.readLine()) != null) {
            content.append(line + " \n");
        }
        reader.close();
        return content.toString();
    }

    /**
     * Read a binary remote resource like Image or PDF from a remote source
     * (http / https) as a File object.
     *
     * @param uri as String
     * @return resource as File
     * @throws java.net.MalformedURLException case of error
     */
    public static byte[] readRemoteResource(final URL uri)
            throws MalformedURLException, IOException {
        try {
            InputStream inputStream = uri.openStream();

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[Constraints.INT_1024];

            int numRead;
            while ((numRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, numRead);
            }
            outputStream.close();
            inputStream.close();

            return outputStream.toByteArray();

        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Reads the full content of a text file in UTF-8.The second parameter
     * charset is optional.
     *
     * @param file as File
     * @param charset as ByteOrderMark (Optional)
     * @return fileContent as String
     * @throws java.io.FileNotFoundException case of error
     * @throws java.io.IOException case of error
     */
    public static String readFileStream(final File file, final ByteOrderMark... charset)
            throws FileNotFoundException, IOException {
        StringBuilder content = new StringBuilder();
        InputStreamReader inputStreamReader = null;
        Charset encoding = CHARSET;
        if (charset.length > 0) {
            String encodingName = charset[0].toString();
            if (encodingName.equals("NONE")) {
                LOGGER.log("ByteOrderMark.NONE converted to UTF-8.", LogLevel.DEBUG);
            } else {
                encoding = Charset.forName(encodingName);
            }
        }
        LOGGER.log("String encoded as " + encoding.displayName(), LogLevel.DEBUG);

        inputStreamReader = new InputStreamReader(new FileInputStream(file), encoding);
        int line;
        while ((line = inputStreamReader.read()) != -1) {
            content.append((char) line);
        }
        inputStreamReader.close();
        return content.toString();
    }

    /**
     * Append content to a given text file at the end of the file in UTF-8.
     *
     * @param filePath as String
     * @param content as String
     * @throws java.io.IOException case of error
     */
    public static void appendFile(final String filePath, final String content)
            throws IOException {
        Files.write(Paths.get(filePath), content.getBytes(CHARSET), StandardOpenOption.APPEND);
        LOGGER.log(filePath + " extended with " + content.length() + " characters",
                LogLevel.DEBUG);
    }

    /**
     * Copy a single File from a source to a destination.
     *
     * @param source as File
     * @param destination as File
     * @throws java.io.FileNotFoundException case of error
     * @throws java.io.IOException case of error
     */
    public static void copyFile(final File source, final File destination)
            throws FileNotFoundException, IOException {
        OutputStream os;
        try (InputStream is = new FileInputStream(source)) {
            os = new FileOutputStream(destination);
            byte[] buffer = new byte[Constraints.INT_1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
        }
        os.close();
    }

    /**
     * Discover a directory and all subdirectories to collect their the files in
     * a List. The list entries are the full path, the filename with file
     * extension. Empty directories will not listed. <br>
     * Example /usr/home/john/file.txt
     *
     * @param directory as File
     * @return a Set of Files
     */
    public static Set<File> listFileTree(final File directory) {
        Set<File> fileTree = new HashSet<>();
        if (directory != null && directory.exists()
                && directory.isDirectory()
                && directory.listFiles().length != 0) {
            for (File entry : directory.listFiles()) {
                if (entry.isFile()) {
                    fileTree.add(entry);
                } else {
                    fileTree.addAll(listFileTree(entry));
                }
            }
        }
        return fileTree;
    }

}