ca.uqac.lif.labpal.FileHelper.java Source code

Java tutorial

Introduction

Here is the source code for ca.uqac.lif.labpal.FileHelper.java

Source

/*
  LabPal, a versatile environment for running experiments on a computer
  Copyright (C) 2015-2017 Sylvain Hall
    
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
    
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.
    
  You should have received a copy of the GNU General Public License
  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package ca.uqac.lif.labpal;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
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.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;

import ca.uqac.lif.jerrydog.InnerFileServer;

/**
 * A number of helpful utilities to read, write and manage files
 * @author Sylvain Hall
 */
public class FileHelper {
    /**
     * The system-dependent carriage return symbol
     */
    public static final transient String CRLF = System.getProperty("line.separator");

    /**
     * The system-dependent symbol for separating paths
     */
    public static final transient String SLASH = System.getProperty("file.separator");

    /**
     * Reads the contents of a file and puts it into a string.
     * @param f The file to read
     * @return The string with the file's contents, or the empty string if
     *   an error occurred. 
     */
    public static String readToString(File f) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        try {
            String sCurrentLine;
            br = new BufferedReader(new FileReader(f));
            while ((sCurrentLine = br.readLine()) != null) {
                sb.append(sCurrentLine).append("\n");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null)
                    br.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return sb.toString();
    }

    /**
     * Reads an input stream and puts its contents into a string
     * @param is The input stream
     * @return The contents
     */
    public static String readToString(InputStream is) {
        String out = "";
        java.util.Scanner s = new java.util.Scanner(is);
        s.useDelimiter("\\A");
        if (s.hasNext()) {
            out = s.next();
        }
        s.close();
        return out;
    }

    /**
     * Reads the contents of a file and puts it into an array of bytes.
     * @param f The file to read
     * @return The array with the file's contents
     */
    public static byte[] readToBytes(File f) {
        FileInputStream fileInputStream = null;
        byte[] bFile = new byte[(int) f.length()];
        try {
            //convert file into array of bytes
            fileInputStream = new FileInputStream(f);
            fileInputStream.read(bFile);
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bFile;
    }

    /**
     * Writes the content of a string to a file
     * @param f The file to write to. If the file does not exist, it will be
     *   created
     * @param content The content to write
     */
    public static void writeFromString(File f, String content) {
        try {
            // if file doesnt exists, then create it
            if (!f.exists()) {
                createIfNotExists(f);
            }
            FileWriter fw = new FileWriter(f.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Creates a file and its parent directory if they do not exist
     * @param f The file to create
     */
    public static void createIfNotExists(File f) {
        File parent = f.getParentFile();
        if (parent == null) {
            return;
        }
        File directory = new File(parent.getAbsolutePath());
        directory.mkdirs();
    }

    /**
     * Writes to a file from an array of bytes
     * @param f The file to write to. If the file does not exist, it will be
     *   created
     * @param bFile The content to write
     */
    public static void writeFromBytes(File f, byte[] bFile) {
        try {
            // if file doesnt exists, then create it
            if (!f.exists()) {
                createIfNotExists(f);
            }
            //convert array of bytes into file
            FileOutputStream fileOuputStream = new FileOutputStream(f);
            fileOuputStream.write(bFile);
            fileOuputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Deletes a file
     * @param filename The filename
     * @return true if the file could be deleted, false otherwise
     */
    public static boolean deleteFile(String filename) {
        File f = new File(filename);
        return f.delete();
    }

    /**
     * Checks whether a file exists in the filesystem
     * @param filename The filename to look for
     * @return true if file exists, false otherwise
     */
    public static boolean fileExists(String filename) {
        File f = new File(filename);
        return f.exists();
    }

    /**
     * Replace the extension of a filename with another. For example,
     * one can replace /my/path/foo.bar with /my/path/foo.baz.
     * @param filename The original filename
     * @param extension The extension to replace with
     * @return The modified filename
     */
    public static String replaceExtension(String filename, String extension) {
        String without_extension = trimExtension(filename);
        return without_extension + "." + extension;
    }

    /**
     * Trims the extension of a filename. For example, with /my/path/foo.bar,
     * would return /my/path/foo
     * @param filename The filename
     * @return The filename without the extension
     */
    public static String trimExtension(String filename) {
        int position = filename.lastIndexOf(".");
        if (position < 0)
            return filename;
        return filename.substring(0, position);
    }

    /**
     * Gets a string from an internal file
     * @param c The class used as reference. The path is expressed relative to
     * the location of this class in the project.
     * @param path The path
     * @return The string, or {@code null} if the path does not correspond
     * to a resource
     */
    public static String internalFileToString(Class<?> c, String path) {
        if (path == null || path.trim().isEmpty()) {
            return null;
        }
        InputStream in = c.getResourceAsStream(path);
        String out;
        try {
            out = streamToString(in);
        } catch (IOException e) {
            return null;
        }
        return out;
    }

    /**
     * Gets an array of bytes from an internal file
     * @param c The class used as reference. The path is expressed relative to
     * the location of this class in the project.
     * @param path The path
     * @return The array of bytes, or {@code null} if the path does not correspond
     * to a resource
     */
    public static byte[] internalFileToBytes(Class<?> c, String path) {
        InputStream in = internalFileToStream(c, path);
        byte[] file_contents = null;
        if (in != null) {
            file_contents = InnerFileServer.readBytes(in);
        }
        return file_contents;
    }

    /**
     * Gets an input stream on an internal file
     * @param c The class used as reference. The path is expressed relative to
     * the location of this class in the project.
     * @param path The path
     * @return An input stream, or {@code null} if the path does not correspond
     * to a resource
     */
    public static InputStream internalFileToStream(Class<?> c, String path) {
        if (path == null || path.trim().isEmpty()) {
            return null;
        }
        InputStream in = c.getResourceAsStream(path);
        return in;
    }

    /**
     * Checks if an internal file exists
     * @param c The reference class
     * @param path The path of the file
     * @return true if the file exists, false otherwise
     */
    public static boolean internalFileExists(Class<?> c, String path) {
        return internalFileToStream(c, path) != null;
    }

    /**
     * Reads a file and puts its contents in a string
     * @param in The input stream to read
     * @return The file's contents, and empty string if the file
     * does not exist
     * @throws IOException If something bad occurs
     */
    public static String streamToString(InputStream in) throws IOException {
        if (in == null) {
            throw new IOException();
        }
        java.util.Scanner scanner = null;
        StringBuilder out = new StringBuilder();
        try {
            scanner = new java.util.Scanner(in, "UTF-8");
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                out.append(line).append(CRLF);
                //out.append(line).append("\n");
            }
        } finally {
            if (scanner != null)
                scanner.close();
        }
        return out.toString();
    }

    /**
     * Checks if a command exists in the system by attempting to run it
     * @param command The command's name
     * @return true if the command could execute, false otherwise
     */
    public static boolean commandExists(String command) {
        // Check if Gnuplot is present
        String[] args = { command, "--version" };
        CommandRunner runner = new CommandRunner(args);
        runner.run();
        return runner.getErrorCode() == 0;
    }

    /**
     * List all files in a folder whose filename matches a regex pattern
     * @param url The source folder
     * @param glob The pattern to match
     * @return The list of file names
     */
    public static List<String> listAllFiles(URL url, String glob) {
        List<String> listing = new ArrayList<String>();
        File f = null;
        try {
            f = new File(url.toURI());
            if (f != null) {
                for (String uris : f.list()) {
                    if (uris.matches(glob)) {
                        listing.add(uris);
                    }
                }
            }
        } catch (URISyntaxException e) {
            // Do nothing
        }
        return listing;
    }

    /**
     * List all files in a folder whose filename matches a regex pattern
     * @param clazz A class reference
     * @param directory The source folder
     * @param glob The pattern to match
     * @return The list of file names
     */
    public static List<String> listAllInternalFiles(Class<?> clazz, String directory, String glob) {
        List<String> listing = new ArrayList<String>();
        File f = null;
        try {
            URI url = clazz.getResource(directory).toURI();
            f = new File(url);
            if (f != null) {
                for (String uris : f.list()) {
                    if (uris.matches(glob)) {
                        listing.add(uris);
                    }
                }
            }
        } catch (URISyntaxException e) {
            // Do nothing
        }
        return listing;
    }

    /**
     * List directory contents for a resource folder. Not recursive.
     * This is basically a brute-force implementation.
     * Works for regular files and also JARs.
     * @author Greg Briggs
     * @param clazz Any java class that lives in the same place as the resources you want.
     * @param path Should end with "/", but not start with one.
     * @param glob The pattern to match
     * @return Just the name of each member item, not the full paths.
     */
    public static List<String> getResourceListing(Class<?> clazz, String path, String glob) {
        return getResourceListing(clazz, path, glob, "");
    }

    /**
     * List directory contents for a resource folder. Not recursive.
     * This is basically a brute-force implementation.
     * Works for regular files and also JARs.
     * @author Greg Briggs
     * @param clazz Any java class that lives in the same place as the resources you want.
     * @param path Should end with "/", but not start with one.
     * @param glob The pattern to match
     * @param exclude_glob The pattern to exclude files
     * @return Just the name of each member item, not the full paths.
     */
    public static List<String> getResourceListing(Class<?> clazz, String path, String glob, String exclude_glob) {
        List<String> names = new ArrayList<String>();
        try {
            URL dirURL = clazz.getClassLoader().getResource(path);
            if (dirURL != null && dirURL.getProtocol().equals("file")) {
                /* A file path: easy enough */
                URI uri = dirURL.toURI();
                File f = new File(uri);
                for (String filename : f.list()) {
                    String f_filename = uri.getRawPath() + filename;
                    File f2 = new File(f_filename);
                    if (f2 != null && f2.isDirectory()) {
                        filename += "/";
                    }
                    if (filename.matches(glob)) {
                        if (!filename.matches(exclude_glob)) {
                            names.add(filename);
                        }
                    }
                }
                return names;
            }

            if (dirURL == null) {
                /* 
                 * In case of a jar file, we can't actually find a directory.
                 * Have to assume the same jar as clazz.
                 */
                String me = clazz.getName().replace(".", "/") + ".class";
                dirURL = clazz.getClassLoader().getResource(me);
            }

            if (dirURL.getProtocol().equals("jar")) {
                /* A JAR path */
                String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
                JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
                Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
                Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
                while (entries.hasMoreElements()) {
                    String name = entries.nextElement().getName();
                    if (name.startsWith(path)) { //filter according to the path
                        String entry = name.substring(path.length());
                        /*int checkSubdir = entry.indexOf("/");
                        if (checkSubdir >= 0)
                        {
                           // if it is a subdirectory, we just return the directory name
                           entry = entry.substring(0, checkSubdir);
                        }*/
                        if (entry.matches(glob)) {
                            if (!entry.matches(exclude_glob)) {
                                result.add(entry);
                            }
                        }
                    }
                }
                jar.close();
                names.addAll(result);
                return names;
            }
        } catch (IOException e) {
            return names;
        } catch (RuntimeException e) {
            return names;
        } catch (URISyntaxException e) {
            return names;
        }
        return names;
    }

    /**
     * Gets a string from an internal file
     * @param o The object used as reference. The path is expressed relative to
     * the location of the object's declaring class in the project.
     * @param filename The path
     * @return The string, or {@code null} if the path does not correspond
     * to a resource or if {@code o} is null
     */
    public static String internalFileToString(Object o, String filename) {
        if (o == null) {
            return null;
        }
        return internalFileToString(o.getClass(), filename);
    }

    /**
     * Merges multiple PDF files into a single file
     * @param dest The destination filename
     * @param paths The input files
     * @return The array of bytes containing the merged PDF
     */
    @SuppressWarnings("deprecation")
    public static byte[] mergePdf(String dest, String... paths) {
        try {
            ByteArrayOutputStream out = null;
            List<File> lst = new ArrayList<File>();
            List<PDDocument> lstPDD = new ArrayList<PDDocument>();
            for (String path : paths) {
                File file1 = new File(path);

                lstPDD.add(PDDocument.load(file1));
                lst.add(file1);
            }
            PDFMergerUtility PDFmerger = new PDFMergerUtility();

            // Setting the destination file
            PDFmerger.setDestinationFileName(dest);
            for (File file : lst) {
                // adding the source files
                PDFmerger.addSource(file);

            }
            // Merging the two documents
            PDFmerger.mergeDocuments();

            for (PDDocument pdd : lstPDD) {
                pdd.close();
            }

            PDDocument pdf = PDDocument.load(new File(dest));

            out = new ByteArrayOutputStream();

            pdf.save(out);
            byte[] data = out.toByteArray();
            pdf.close();
            return data;
        } catch (IOException e) {
            Logger.getAnonymousLogger().log(Level.SEVERE, e.getMessage());
        }
        return null;
    }

}