/* * Eoulsan development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public License version 2.1 or * later and CeCILL-C. This should be distributed with the code. * If you do not have a copy, see: * * http://www.gnu.org/licenses/lgpl-2.1.txt * http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt * * Copyright for this code is held jointly by the Genomic platform * of the Institut de Biologie de l'École normale supérieure and * the individual authors. These should be listed in @author doc * comments. * * For more information on the Eoulsan project and its aims, * or to join the Eoulsan Google group, visit the home page * at: * * http://outils.genomique.biologie.ens.fr/eoulsan * */ package fr.ens.biologie.genomique.eoulsan.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.math.BigInteger; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import fr.ens.biologie.genomique.eoulsan.io.CompressionType; import fr.ens.biologie.genomique.eoulsan.io.FileCharsets; /** * This class define useful method to handle files. * @since 1.0 * @author Laurent Jourdren */ public class FileUtils { /** The default size of the buffer. */ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; private static final boolean USE_CHANNEL = false; /** * Simple FilenameFilter to filter Paths with their prefix. * @author Laurent Jourdren */ public static final class PrefixFilenameFilter implements FilenameFilter { private final String prefix; private final boolean allowCompressedFile; @Override public boolean accept(final File file, final String name) { if (name == null) { return false; } final String myName; if (this.allowCompressedFile) { myName = StringUtils.removeCompressedExtensionFromFilename(name); } else { myName = name; } return myName.startsWith(this.prefix); } // // Constructor // /** * Public constructor. * @param prefix the prefix for the filter */ public PrefixFilenameFilter(final String prefix) { this(prefix, false); } /** * Public constructor. * @param prefix the prefix for the filter * @param allowCompressedFile allow files with a compressed extension */ public PrefixFilenameFilter(final String prefix, final boolean allowCompressedFile) { if (prefix == null) { throw new NullPointerException("The prefix is null"); } this.prefix = prefix; this.allowCompressedFile = allowCompressedFile; } } /** * Simple FilenameFilter to filter Paths with their suffix. * @author Laurent Jourdren */ public static final class SuffixFilenameFilter implements FilenameFilter { private final String suffix; private final boolean allowCompressedFile; @Override public boolean accept(final File file, final String name) { if (name == null) { return false; } final String myName; if (this.allowCompressedFile) { myName = StringUtils.removeCompressedExtensionFromFilename(name); } else { myName = name; } return myName.endsWith(this.suffix); } // // Constructor // /** * Public constructor. * @param suffix the suffix for the filter */ public SuffixFilenameFilter(final String suffix) { this(suffix, false); } /** * Public constructor. * @param suffix the suffix for the filter * @param allowCompressedFile allow files with a compressed extension */ public SuffixFilenameFilter(final String suffix, final boolean allowCompressedFile) { if (suffix == null) { throw new NullPointerException("The suffix is null"); } this.suffix = suffix; this.allowCompressedFile = allowCompressedFile; } } /** * Utility method to create a fast InputStream from a file. * @param filename name of the file to read * @return an InputStream * @throws FileNotFoundException if the file is not found */ public static final InputStream createInputStream(final String filename) throws FileNotFoundException { if (filename == null) { throw new NullPointerException("The filename is null."); } return createInputStream(new File(filename)); } /** * Utility method to create a fast InputStream from a file. * @param file File to read * @return an InputStream * @throws FileNotFoundException if the file is not found */ public static final InputStream createInputStream(final File file) throws FileNotFoundException { if (file == null) { throw new NullPointerException("The file is null."); } if (file.isDirectory()) { throw new FileNotFoundException("The file is a directory: " + file); } if (USE_CHANNEL) { final FileInputStream inFile = new FileInputStream(file); final FileChannel inChannel = inFile.getChannel(); return Channels.newInputStream(inChannel); } return new FileInputStream(file); } /** * Utility method to create a fast OutputStream from a file. * @param filename Name of the file to read * @return an OutputStream * @throws IOException if the file is not found */ public static final OutputStream createOutputStream(final String filename) throws IOException { if (filename == null) { throw new NullPointerException("The filename is null."); } return createOutputStream(new File(filename)); } /** * Utility method to create a fast OutputStream from a file. * @param file File to read * @return an InputStream * @throws IOException if the file is not found */ public static final OutputStream createOutputStream(final File file) throws IOException { if (file == null) { throw new NullPointerException("The file is null."); } if (file.isFile()) { if (!file.delete()) { throw new IOException( "Can not remove existing file: " + file.getAbsolutePath()); } } if (USE_CHANNEL) { final FileOutputStream outFile = new FileOutputStream(file); final FileChannel outChannel = outFile.getChannel(); return Channels.newOutputStream(outChannel); } return new FileOutputStream(file); } /** * Utility method to create fast BufferedReader. * @param filename Name of the file to read * @return a BufferedReader * @throws FileNotFoundException if the file is not found */ public static final BufferedReader createBufferedReader(final String filename) throws FileNotFoundException { return createBufferedReader(filename, null); } /** * Utility method to create fast BufferedReader. * @param filename Name of the file to read * @param charset Charset to use * @return a BufferedReader * @throws FileNotFoundException if the file is not found */ public static final BufferedReader createBufferedReader(final String filename, final Charset charset) throws FileNotFoundException { if (filename == null) { throw new NullPointerException("The filename is null"); } return createBufferedReader(new File(filename), charset); } /** * Utility method to create fast BufferedReader. * @param file File to read * @return a BufferedReader * @throws FileNotFoundException if the file is not found */ public static final BufferedReader createBufferedReader(final File file) throws FileNotFoundException { return createBufferedReader(file, null); } /** * Utility method to create fast BufferedReader. * @param file File to read * @param charset Charset to use * @return a BufferedReader * @throws FileNotFoundException if the file is not found */ public static final BufferedReader createBufferedReader(final File file, final Charset charset) throws FileNotFoundException { final InputStream is = createInputStream(file); if (charset != null) { return new BufferedReader(new InputStreamReader(is, charset)); } return new BufferedReader( new InputStreamReader(is, FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast BufferedReader. * @param is InputStream to read * @return a BufferedReader */ public static final BufferedReader createBufferedReader( final InputStream is) { return createBufferedReader(is, null); } /** * Utility method to create fast BufferedReader. * @param is InputStream to read * @param charset Charset to use * @return a BufferedReader */ public static final BufferedReader createBufferedReader(final InputStream is, final Charset charset) { if (is == null) { throw new NullPointerException("The input stream is null"); } if (charset != null) { return new BufferedReader(new InputStreamReader(is, charset)); } return new BufferedReader( new InputStreamReader(is, FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param filename Name of the file to write * @param charset Charset to use * @return a BufferedWriter * @throws IOException if the file is not found */ public static final UnSynchronizedBufferedWriter createFastBufferedWriter( final String filename, final Charset charset) throws IOException { if (filename == null) { throw new NullPointerException("The filename is null"); } return createFastBufferedWriter(new File(filename), charset); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param filename Name of the file to write * @return a BufferedWriter * @throws IOException if the file is not found */ public static final UnSynchronizedBufferedWriter createFastBufferedWriter( final String filename) throws IOException { return createFastBufferedWriter(filename, null); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param file File to write * @return a BufferedWriter * @throws IOException if the file is not found */ public static final UnSynchronizedBufferedWriter createFastBufferedWriter( final File file) throws IOException { return createFastBufferedWriter(file, null); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param file File to write * @param charset Charset to use * @return a BufferedWriter * @throws IOException if the file is not found */ public static final UnSynchronizedBufferedWriter createFastBufferedWriter( final File file, final Charset charset) throws IOException { final OutputStream os = createOutputStream(file); return new UnSynchronizedBufferedWriter(new OutputStreamWriter(os, charset != null ? charset : FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param os OutputStream to write * @return a BufferedWriter * @throws FileNotFoundException if the file is not found */ public static final UnSynchronizedBufferedWriter createFastBufferedWriter( final OutputStream os) throws FileNotFoundException { return createFastBufferedWriter(os, null); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param os OutputStream to write * @return a BufferedWriter * @throws FileNotFoundException if the file is not found */ public static final UnSynchronizedBufferedWriter createFastBufferedWriter( final OutputStream os, final Charset charset) throws FileNotFoundException { if (os == null) { throw new NullPointerException("The output stream is null"); } return new UnSynchronizedBufferedWriter(new OutputStreamWriter(os, charset != null ? charset : FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. The created file use default encoding. * @param file File to write * @return a BufferedWriter * @throws IOException if an error occurs while creating the Writer */ public static final UnSynchronizedBufferedWriter createFastBufferedGZipWriter( final File file) throws IOException { if (file == null) { return null; } // Remove file if exists if (file.exists()) { if (!file.delete()) { throw new IOException( "Can not remove existing file: " + file.getAbsolutePath()); } } final FileOutputStream outFile = new FileOutputStream(file); final FileChannel outChannel = outFile.getChannel(); final OutputStream gzos = CompressionType .createGZipOutputStream(Channels.newOutputStream(outChannel)); return new UnSynchronizedBufferedWriter( new OutputStreamWriter(gzos, FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param filename Name of the file to write * @return a BufferedWriter * @throws IOException if the file is not found */ public static final BufferedWriter createBufferedWriter(final String filename) throws IOException { return createBufferedWriter(filename, null); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param filename Name of the file to write * @param charset Charset to use * @return a BufferedWriter * @throws IOException if the file is not found */ public static final BufferedWriter createBufferedWriter(final String filename, final Charset charset) throws IOException { if (filename == null) { throw new NullPointerException("The filename is null"); } return createBufferedWriter(new File(filename), charset); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param file File to write * @return a BufferedWriter * @throws IOException if the file is not found */ public static final BufferedWriter createBufferedWriter(final File file) throws IOException { return createBufferedWriter(file, null); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param file File to write * @param charset Charset to use * @return a BufferedWriter * @throws IOException if the file is not found */ public static final BufferedWriter createBufferedWriter(final File file, final Charset charset) throws IOException { final OutputStream os = createOutputStream(file); return new BufferedWriter(new OutputStreamWriter(os, charset != null ? charset : FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param os OutputStream to write * @return a BufferedWriter * @throws FileNotFoundException if the file is not found */ public static final BufferedWriter createBufferedWriter(final OutputStream os) throws FileNotFoundException { return createBufferedWriter(os, null); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. * @param os OutputStream to write * @param charset Charset to use * @return a BufferedWriter * @throws FileNotFoundException if the file is not found */ public static final BufferedWriter createBufferedWriter(final OutputStream os, final Charset charset) throws FileNotFoundException { if (os == null) { throw new NullPointerException("The output stream is null"); } return new BufferedWriter(new OutputStreamWriter(os, charset != null ? charset : FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast BufferedWriter. Warning the buffer is not * safe-thread. The created file use default encoding. * @param file File to write * @return a BufferedWriter * @throws IOException if an error occurs while creating the Writer */ public static final BufferedWriter createBufferedGZipWriter(final File file) throws IOException { if (file == null) { return null; } // Remove file if exists if (file.exists()) { if (!file.delete()) { throw new IOException( "Can not remove existing file: " + file.getAbsolutePath()); } } final FileOutputStream outFile = new FileOutputStream(file); final FileChannel outChannel = outFile.getChannel(); final OutputStream gzos = CompressionType .createGZipOutputStream(Channels.newOutputStream(outChannel)); return new BufferedWriter( new OutputStreamWriter(gzos, FileCharsets.SYSTEM_CHARSET)); } /** * Utility method to create fast ObjectOutput. * @param file File to write * @return a ObjectOutput * @throws IOException if an error occurs while creating the Writer */ public static final ObjectOutputStream createObjectOutputWriter( final File file) throws IOException { if (file == null) { return null; } // Remove file if exists if (file.exists()) { if (!file.delete()) { throw new IOException( "Can not remove existing file: " + file.getAbsolutePath()); } } final FileOutputStream outFile = new FileOutputStream(file); final FileChannel outChannel = outFile.getChannel(); return new ObjectOutputStream(Channels.newOutputStream(outChannel)); } /** * Utility method to create fast ObjectInputStream. * @param file File to read * @return a ObjectInputStream * @throws IOException if an error occurs while creating the reader */ public static final ObjectInputStream createObjectInputReader(final File file) throws IOException { if (file == null) { return null; } final FileInputStream inFile = new FileInputStream(file); final FileChannel inChannel = inFile.getChannel(); return new ObjectInputStream(Channels.newInputStream(inChannel)); } /** * Copy bytes from an InputStream to an OutputStream. * @param input the InputStream to read from * @param output the OutputStream to write to * @return the number of bytes copied * @throws IOException In case of an I/O problem */ public static long copy(final InputStream input, final OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } input.close(); output.close(); return count; } /** * Copy bytes from an InputStream to an OutputStream without closing the * outputStream. * @param input the InputStream to read from * @param output the OutputStream to write to * @return the number of bytes copied * @throws IOException In case of an I/O problem */ public static long append(final InputStream input, final OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } input.close(); return count; } /** * Copy a file. * @param srcFile File to copy * @param destFile Destination file * @throws IOException if an error occurs while copying file */ public static boolean copyFile(final File srcFile, final File destFile) throws IOException { return copyFile(srcFile, destFile, false); } /** * Copy a file. * @param srcFile File to copy * @param destFile Destination file * @param overwrite overwrite existing file * @throws IOException if an error occurs while copying file */ public static boolean copyFile(final File srcFile, final File destFile, final boolean overwrite) throws IOException { if (srcFile == null) { throw new NullPointerException("Input file is null"); } if (destFile == null) { throw new NullPointerException("output file is null"); } if (!srcFile.exists()) { throw new IOException("Source file doesn't exists: " + srcFile); } if (srcFile.isDirectory()) { throw new IOException("Can't copy/move a directory: " + srcFile); } final File myDestFile; if (destFile.isDirectory()) { myDestFile = new File(destFile, srcFile.getName()); } else { myDestFile = destFile; } if (destFile.exists()) { if (!overwrite) { return false; } if (!myDestFile.delete()) { throw new IOException( "Can not remove existing file: " + myDestFile.getAbsolutePath()); } } final FileChannel inChannel = new FileInputStream(srcFile).getChannel(); final FileChannel outChannel = new FileOutputStream(myDestFile).getChannel(); try { inChannel.transferTo(0, inChannel.size(), outChannel); } finally { if (inChannel != null) { inChannel.close(); } if (outChannel != null) { outChannel.close(); } } return true; } /** * Copy a file. * @param srcFile File to copy * @param destFile Destination file * @throws IOException if an error occurs while copying file */ public static boolean moveFile(final File srcFile, final File destFile) throws IOException { return moveFile(srcFile, destFile, true); } /** * Copy a file. * @param srcFile File to copy * @param destFile Destination file * @param overwrite overwrite existing file * @throws IOException if an error occurs while copying file */ public static boolean moveFile(final File srcFile, final File destFile, final boolean overwrite) throws IOException { return copyFile(srcFile, destFile, overwrite) && srcFile.delete(); } /** * Create a zip archive with the content of a directory. * @param directory directory to compress * @param zipFile output file * @throws IOException if an error occurs while compressing data */ public static void createZip(final File directory, final File zipFile) throws IOException { if (directory == null) { throw new IOException("Input directory is null"); } if (!(directory.exists() && directory.isDirectory())) { throw new IOException("Invalid directory (" + directory + ")"); } if (zipFile == null) { throw new IOException("Output file is null"); } final ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile)); zipFolder(directory, "", out); out.close(); } private static void zipFolder(final File directory, final String path, final ZipOutputStream out) throws IOException { // Add directory even empty if (!"".equals(path)) { out.putNextEntry(new ZipEntry(path)); } // Get the list of files to add final File[] filesToAdd = directory.listFiles(new FileFilter() { @Override public boolean accept(final File file) { return file.isFile(); } }); // Add the files if (filesToAdd != null) { final byte data[] = new byte[DEFAULT_BUFFER_SIZE]; BufferedInputStream origin = null; for (final File f : filesToAdd) { out.putNextEntry(new ZipEntry(path + f.getName())); final FileInputStream fi = new FileInputStream(f); origin = new BufferedInputStream(fi, DEFAULT_BUFFER_SIZE); int count; while ((count = origin.read(data, 0, DEFAULT_BUFFER_SIZE)) != -1) { out.write(data, 0, count); } origin.close(); } } // Get the list of directories to add final File[] directoriesToAdd = directory.listFiles(new FileFilter() { @Override public boolean accept(final File file) { return file.isDirectory(); } }); // Add directories if (directoriesToAdd != null) { for (final File dir : directoriesToAdd) { zipFolder(dir, path + File.separator + dir.getName() + File.separator, out); } } } /** * Unzip a zip file in a directory. * @param is input stream of the zip file * @param outputDirectory output directory * @throws IOException if an error occurs while unzipping the file */ public static void unzip(final InputStream is, final File outputDirectory) throws IOException { if (is == null) { throw new IOException("The inputStream is null"); } if (outputDirectory == null) { throw new IOException("The output directory is null"); } if (!(outputDirectory.exists() && outputDirectory.isDirectory())) { throw new IOException( "The output directory is invalid (" + outputDirectory + ")"); } BufferedOutputStream dest = null; final ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is)); ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { final File newFile = new File(outputDirectory + File.separator + entry.getName()); if (entry.isDirectory()) { if (!newFile.exists()) { if (!newFile.mkdirs()) { throw new IOException("Cannot create directory: " + newFile); } } } else { final File parentFile = newFile.getParentFile(); if (!parentFile.exists()) { if (!parentFile.mkdirs()) { throw new IOException("Cannot create directory: " + parentFile); } } int count; byte data[] = new byte[DEFAULT_BUFFER_SIZE]; // write the files to the disk FileOutputStream fos = new FileOutputStream(newFile); dest = new BufferedOutputStream(fos, DEFAULT_BUFFER_SIZE); while ((count = zis.read(data, 0, DEFAULT_BUFFER_SIZE)) != -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); } } zis.close(); } /** * Unzip a zip file in a directory. * @param zipFile The zip file * @param outputDirectory The output directory * @throws IOException if an issue occurs while unzipping the file */ public static void unzip(final File zipFile, final File outputDirectory) throws IOException { if (zipFile == null) { throw new IOException("The zip file is null"); } if (!(zipFile.exists() && zipFile.isFile())) { throw new IOException("Invalid zip file (" + zipFile.getName() + ")"); } unzip(new FileInputStream(zipFile), outputDirectory); } /** * Get the files of a directory. * @param directory Directory to list files * @param extension extension of the file * @return an array of File objects */ public static File[] listFilesByExtension(final File directory, final String extension) { if (directory == null || extension == null) { return null; } return directory.listFiles(new FilenameFilter() { @Override public boolean accept(final File arg0, final String arg1) { return arg1.endsWith(extension); } }); } /** * Remove a list of files. * @param filesToRemove An array with the files to remove * @param recursive true if the remove must be recursive */ public static boolean removeFiles(final File[] filesToRemove, final boolean recursive) { if (filesToRemove == null) { return false; } for (final File f : filesToRemove) { if (f.isDirectory()) { if (recursive) { if (!removeFiles(listFilesByExtension(f, ""), true)) { return false; } if (!f.delete()) { return false; } } } else if (!f.delete()) { return false; } } return true; } /** * Get the prefix of a list of files. * @param files Files that we wants the prefix * @return the prefix of the files */ public static String getPrefix(final List<File> files) { if (files == null) { return null; } File[] param = new File[files.size()]; files.toArray(param); return getPrefix(param); } /** * Get the prefix of a list of files. * @param files Files that we wants the prefix * @return the prefix of the files */ public static String getPrefix(final File[] files) { if (files == null) { return null; } String prefix = null; final StringBuilder sb = new StringBuilder(); for (File file : files) { String filename = file.getName(); if (prefix == null) { prefix = filename; } else if (!filename.startsWith(prefix)) { int max = Math.min(prefix.length(), filename.length()); for (int j = 0; j < max; j++) { if (prefix.charAt(j) == filename.charAt(j)) { sb.append(prefix.charAt(j)); } } prefix = sb.toString(); sb.setLength(0); } } return prefix; } /** * Delete a directory and its content. It is not a recursive method. * @param directory Directory to remove * @return false if one of the files can't be removed */ public static boolean removeDirectory(final File directory) { if (directory == null) { return false; } final File[] files = directory.listFiles(); for (File file : files) { if (!file.delete()) { return false; } } return directory.delete(); } /** * Concat a list of files * @param files files to concat * @param outputFile output file * @throws IOException if an error occurs while read or writing data */ public static void concat(final List<File> files, final File outputFile) throws IOException { if (files == null) { throw new NullPointerException("Files to concat is null"); } if (outputFile == null) { throw new NullPointerException("Output file is null"); } UnSynchronizedBufferedWriter writer = createFastBufferedWriter(outputFile); for (File f : files) { BufferedReader reader = createBufferedReader(f); String line; while ((line = reader.readLine()) != null) { writer.write(line + "\n"); } } writer.close(); } /** * Create a new temporary file. * @param prefix Prefix of the temporary file * @param suffix suffix of the temporary file * @return the new temporary file * @throws IOException if there is an error creating the temporary directory */ public static File createTempFile(final String prefix, final String suffix) throws IOException { return createTempFile(null, prefix, suffix); } /** * Create a file in the temporary directory. * @param filename The filename to create * @return The new File */ public static File createFileInTempDir(final String filename) { return new File(System.getProperty("java.io.tmpdir"), filename); } /** * Create a new temporary file. * @param directory parent directory of the temporary file to create * @param prefix Prefix of the temporary file * @param suffix suffix of the temporary file * @return the new temporary file * @throws IOException if there is an error creating the temporary directory */ public static File createTempFile(final File directory, final String prefix, final String suffix) throws IOException { final File myDir; final String myPrefix; final String mySuffix; if (directory == null) { myDir = new File(System.getProperty("java.io.tmpdir")); } else { myDir = directory; } if (prefix == null) { myPrefix = ""; } else { myPrefix = prefix; } if (suffix == null) { mySuffix = ""; } else { mySuffix = suffix; } File tempFile; final int maxAttempts = 9; int attemptCount = 0; do { attemptCount++; if (attemptCount > maxAttempts) { throw new IOException("The highly improbable has occurred! Failed to " + "create a unique temporary directory after " + maxAttempts + " attempts."); } final String filename = myPrefix + UUID.randomUUID().toString() + mySuffix; tempFile = new File(myDir, filename); } while (tempFile.exists()); if (!tempFile.createNewFile()) { throw new IOException( "Failed to create temp file named " + tempFile.getAbsolutePath()); } return tempFile; } /** * Create a new temporary directory. * @return the new directory * @throws IOException if there is an error creating the temporary directory */ public static File createTempDir() throws IOException { return createTempDir(null, null); } /** * Create a new temporary directory. * @param prefix prefix of the temporary directory * @return the new directory * @throws IOException if there is an error creating the temporary directory */ public static File createTempDir(final String prefix) throws IOException { return createTempDir(null, prefix); } /** * Create a new temporary directory. * @param parentDirectory parent directory for the temporary directory * @return the new directory * @throws IOException if there is an error creating the temporary directory */ public static File createTempDir(final File parentDirectory) throws IOException { return createTempDir(parentDirectory, null); } /** * Create a new temporary directory. * @param parentDirectory parent directory for the temporary directory * @param prefix Prefix of the directory name * @return the new directory * @throws IOException if there is an error creating the temporary directory */ public static File createTempDir(final File parentDirectory, final String prefix) throws IOException { final File myTempParentDir; final String myPrefix; if (parentDirectory == null) { myTempParentDir = new File(System.getProperty("java.io.tmpdir")); } else { myTempParentDir = parentDirectory; } if (prefix == null) { myPrefix = ""; } else { myPrefix = prefix; } File newTempDir; final int maxAttempts = 9; int attemptCount = 0; do { attemptCount++; if (attemptCount > maxAttempts) { throw new IOException("The highly improbable has occurred! Failed to " + "create a unique temporary directory after " + maxAttempts + " attempts."); } String dirName = myPrefix + UUID.randomUUID().toString(); newTempDir = new File(myTempParentDir, dirName); } while (newTempDir.exists()); if (newTempDir.mkdirs()) { return newTempDir; } throw new IOException( "Failed to create temp dir named " + newTempDir.getAbsolutePath()); } /** * Recursively delete file or directory * @param fileOrDir the file or dir to delete * @return true if all files are successfully deleted */ public static boolean recursiveDelete(final File fileOrDir) { if (fileOrDir == null) { return false; } if (fileOrDir.isDirectory()) { // recursively delete contents for (File innerFile : fileOrDir.listFiles()) { if (!recursiveDelete(innerFile)) { return false; } } } return fileOrDir.delete(); } /** * Check if a file exists * @param file File to test * @param msgFileType message for the description of the file * @throws IOException if the file doesn't exists */ public static final void checkExistingFile(final File file, final String msgFileType) throws IOException { if (msgFileType == null) { throw new NullPointerException( "Message file type for check isn't defined"); } if (file == null) { throw new NullPointerException("The " + msgFileType + " is not defined. Please check and define " + msgFileType + " path and/or files."); } if (!file.exists()) { throw new IOException( "The " + msgFileType + " does not exists: " + file.getAbsolutePath()); } } /** * Check if a directory exists * @param directory directory to test * @param msgFileType message for the description of the file * @throws IOException if the file doesn't exists */ public static final void checkExistingDirectoryFile(final File directory, final String msgFileType) throws IOException { checkExistingFile(directory, msgFileType); if (!directory.isDirectory()) { throw new IOException("The " + msgFileType + " is not a directory: " + directory.getAbsolutePath()); } } /** * Check if a file exists * @param file File to test * @param msgFileType message for the description of the file * @throws IOException if the file doesn't exists */ public static final void checkExistingStandardFile(final File file, final String msgFileType) throws IOException { checkExistingFile(file, msgFileType); if (!file.isFile()) { throw new IOException("The " + msgFileType + " is not a standard file: " + file.getAbsolutePath()); } } /** * Check if a file exists * @param file File to test * @param msgFileType message for the description of the file * @throws IOException if the file doesn't exists */ public static final void checkExistingStandardFileOrDirectory(final File file, final String msgFileType) throws IOException { checkExistingDirectoryFile(file, msgFileType); if (!file.isFile() && !file.isDirectory()) { throw new IOException("The " + msgFileType + " is not a standard file or a directory: " + file.getAbsolutePath()); } } /** * Test if two stream are equals * @param a First stream to compare * @param b Second stream to compare * @return true if the two stream are equals * @throws IOException if an error occurs while reading the streams */ public static boolean compareFile(final InputStream a, final InputStream b) throws IOException { if (a == null && b == null) { return true; } if (a == null || b == null) { return false; } boolean end = false; boolean result = true; while (!end) { int ca = a.read(); int cb = b.read(); if (ca != cb) { result = false; end = true; } if (ca == -1) { end = true; } } a.close(); b.close(); return result; } /** * Test if two stream are equals * @param filenameA First filename to compare * @param filenameB Second filename to compare * @return true if the two stream are equals * @throws IOException if an error occurs while reading the streams */ public static boolean compareFile(final String filenameA, final String filenameB) throws IOException { return compareFile(new File(filenameA), new File(filenameB)); } /** * Test if two stream are equals * @param fileA First filename to compare * @param fileB Second filename to compare * @return true if the two stream are equals * @throws IOException if an error occurs while reading the streams */ public static boolean compareFile(final File fileA, final File fileB) throws IOException { InputStream isa = null; InputStream isb = null; try { isa = new FileInputStream(fileA); isb = new FileInputStream(fileB); return compareFile(isa, isb); } finally { if (isa != null) { isa.close(); } if (isb != null) { isb.close(); } } } /** * Compute MD5 sum of a file. * @param file the input file * @return a string with the MD5 sum * @throws IOException In case of an I/O problem or digest error */ public static String computeMD5Sum(final File file) throws IOException { if (file == null) { throw new NullPointerException("The file argument is null"); } return computeMD5Sum(new FileInputStream(file)); } /** * Compute MD5 sum of a file. * @param input the InputStream to read from * @return a string with the MD5 sum * @throws IOException In case of an I/O problem or digest error */ public static String computeMD5Sum(final InputStream input) throws IOException { final MessageDigest md5Digest; try { md5Digest = MessageDigest.getInstance("MD5"); byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int n = 0; while (-1 != (n = input.read(buffer))) { md5Digest.update(buffer, 0, n); } } catch (NoSuchAlgorithmException e) { throw new IOException("No MD5 digest algorithm found: " + e.getMessage()); } input.close(); final BigInteger bigInt = new BigInteger(1, md5Digest.digest()); return bigInt.toString(16); } /** * Relativize a path from a base path. * @param path path to relativize * @param base base path (must be a directory) * @return a File object with the relative path */ public static final File relativizePath(final File path, final File base) { if (path == null) { throw new NullPointerException("The path is null"); } if (base == null) { return path; } final File absPath = path.getAbsoluteFile(); final File absBase = base.getAbsoluteFile(); List<String> pathNodes = new ArrayList<>(); List<String> baseNodes = new ArrayList<>(); File parent = absPath; do { pathNodes.add(parent.getName()); } while ((parent = parent.getParentFile()) != null); parent = absBase; do { baseNodes.add(parent.getName()); } while ((parent = parent.getParentFile()) != null); Collections.reverse(pathNodes); Collections.reverse(baseNodes); final int minSize = Math.min(pathNodes.size(), baseNodes.size()); int i = 0; while (i < minSize && pathNodes.get(i).equals(baseNodes.get(i))) { i++; } final List<String> resultNodes = new ArrayList<>(); if (i < baseNodes.size()) { for (int j = 0; j < baseNodes.size() - i; j++) { resultNodes.add(".."); } } resultNodes.addAll(pathNodes.subList(i, pathNodes.size())); return createFile(resultNodes); } /** * Create a File object from a list of the node of the file path. * @param pathNodes the list of the nodes of the path * @return a new File object with the requested path */ private static File createFile(final List<String> pathNodes) { File result = null; for (String f : pathNodes) { if (result == null) { result = new File(f); } else { result = new File(result, f); } } return result; } /** * Create a named pipe. * @param file path of the named pipe * @throws IOException if an error occurs while creating the named pipe */ public static void createNamedPipe(final File file) throws IOException { if (file == null) { throw new NullPointerException("file argument cannot be null"); } if (file.exists()) { throw new IOException("Named pipe to create already exists: " + file); } final Process process = new ProcessBuilder("mkfifo", file.getAbsolutePath()).start(); int exitCode; try { exitCode = process.waitFor(); if (exitCode != 0) { throw new IOException("Unable to create named pipe: " + file); } } catch (InterruptedException e) { throw new IOException("Unable to create named pipe: " + file, e); } } /** * Check if an executable is in the PATH. * @param executableName the name of the executable * @return true if an executable is in the PATH */ public static boolean checkIfExecutableIsInPATH(final String executableName) { if (executableName == null) { throw new NullPointerException("executableName argument cannot be null"); } final String pathEnv = System.getenv("PATH"); if (pathEnv == null) { return false; } final FilenameFilter filter = new FilenameFilter() { @Override public boolean accept(final File dir, final String name) { return executableName.equals(name); } }; final String[] paths = pathEnv.split(":"); for (String path : paths) { path = path.trim(); if (path.isEmpty()) { continue; } File f = new File(path); if (!f.exists()) { continue; } if (f.isFile()) { if (executableName.equals(f.getName())) { return true; } } else { final File[] files = f.listFiles(filter); if (files != null && files.length > 0) { return true; } } } return false; } }