package com.jdroid.java.utils; import com.jdroid.java.exception.UnexpectedException; import org.slf4j.Logger; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Closeable; 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.io.PrintWriter; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * This class contains functions for working with files within the application. */ public abstract class FileUtils { private static final Logger LOGGER = LoggerUtils.getLogger(FileUtils.class); // Amount of bytes on a megabyte public static final int BYTES_TO_MB = 1048576; private static final int BUFFER_SIZE = 16384; /** * Reads the inputStream and returns a byte array with all the information * * @param inputStream The inputStream to be read * @return A byte array with all the inputStream's information * @throws IOException The exception thrown when an error reading the inputStream happens */ public static byte[] readAsBytes(InputStream inputStream) throws IOException { byte[] buffer = new byte[BUFFER_SIZE]; InputStream is = new BufferedInputStream(inputStream); try { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int cnt = is.read(buffer); while (cnt != -1) { outputStream.write(buffer, 0, cnt); cnt = is.read(buffer); } return outputStream.toByteArray(); } finally { safeClose(is); } } /** * Reads the file and returns a byte array with all the information * * @param file The file to be read * @return A byte array with all the file's information * @throws IOException The exception thrown when an error reading the file happens */ @SuppressWarnings("resource") public static byte[] readAsBytes(File file) throws IOException { return readAsBytes(new FileInputStream(file)); } /** * @param filePath The path to the file * @return a file */ public static File checkFile(String filePath) { File file = new File(filePath); if (!FileUtils.exist(filePath)) { file.mkdirs(); } return file; } /** * @param filePath The file path to the file for verify the existence * @return True if exist a file with in the file path */ public static boolean exist(String filePath) { return new File(filePath).exists(); } /** * Deletes an instance of {@link File} even if it is a directory containing files.<br> * If the file is a directory and has contents, then executes itself on every content. * * @see File#delete() * @param file The {@link File} to be deleted. */ public static void forceDelete(File file) { if (file.exists()) { // If the File instance to delete is a directory, delete all it's // contents. if (file.isDirectory()) { File[] listFiles = file.listFiles(); if (listFiles != null) { for (File contentFile : listFiles) { FileUtils.forceDelete(contentFile); } } } if (file.delete()) { LOGGER.debug("File " + file.getPath() + " was successfully deleted."); } else { LOGGER.warn("File " + file.getPath() + " couldn't be deleted."); } } } /** * Renames or moves a determined {@link File} instance to a destination defined by another {@link File} instance.<br> * Differs from the {@link File#renameTo(File)} method in the fact that this method logs if the operation was * successful.<br> * * @see File#renameTo(File) * @param fileToBeMoved The file to be renamed or moved. * @param destination The {@link File} instance that denotes the new location * @return <b>boolean</b> true if the file has been successfully renamed or moved. */ public static boolean renameOrMove(File fileToBeMoved, File destination) { boolean result = fileToBeMoved.renameTo(destination); if (result) { LOGGER.debug("File " + fileToBeMoved.getPath() + " was succesfully renamed or moved."); } else { LOGGER.error("File " + fileToBeMoved.getPath() + " couldn't be renamed or moved."); } return result; } public static File createTempFile() { File file; try { file = File.createTempFile("tempFile", ".tmp"); } catch (IOException e) { throw new UnexpectedException(e); } return file; } public static File createTempDir() { File file = FileUtils.createTempFile(); File dir = new File(file.getAbsolutePath() + "dir"); dir.mkdir(); return dir; } public static File toTempFile(String content) { File file; try { file = File.createTempFile("tempFile", ".tmp"); } catch (IOException e) { throw new UnexpectedException(e); } try { PrintWriter printWriter = new PrintWriter(file); printWriter.append(content); printWriter.close(); return file; } catch (FileNotFoundException e) { throw new UnexpectedException(e); } } public static void createFile(String content, String parentPath, String fileName) { try { new File(parentPath).mkdirs(); PrintWriter printWriter = new PrintWriter(parentPath + File.separatorChar + fileName); printWriter.append(StringUtils.defaultString(content)); printWriter.close(); } catch (FileNotFoundException e) { throw new UnexpectedException(e); } } /** * Receives a File and iterates over all its lines and returns a String. * * @param file The file * @return The content of the file as String */ public static String toString(File file) { try { return FileUtils.toString(new FileInputStream(file)); } catch (FileNotFoundException e) { throw new UnexpectedException( new StringBuilder("The file doesn't exist [").append(file).append("]").toString(), e); } } public static String toString(InputStream in, Boolean closeStream) { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder contentBuilder = new StringBuilder(); String text = null; // repeat until all lines are read try { Boolean firstLine = true; while ((text = reader.readLine()) != null) { if (!firstLine) { contentBuilder.append(System.getProperty("line.separator")); } firstLine = false; contentBuilder.append(text); } } catch (IOException e) { throw new UnexpectedException("Error reading the stream", e); } finally { if (closeStream) { safeClose(in); } } return contentBuilder.toString(); } /** * Receives an InputStream and iterates over all its lines and returns a String. * * @param in the InputStream to be converted * @return The content of the file as String */ public static String toString(InputStream in) { return toString(in, true); } /** * @param source the source {@link InputStream} * @param target the target {@link File} */ @SuppressWarnings("resource") public static void copyStream(InputStream source, File target) { FileOutputStream out = null; try { File dir = target.getParentFile(); if (dir != null) { dir.mkdirs(); } out = new FileOutputStream(target); FileUtils.copyStream(source, out); } catch (IOException e) { throw new UnexpectedException( new StringBuilder("Error copying the file to [").append(target).append("]").toString(), e); } finally { safeClose(out); } } /** * @param source the source {@link InputStream} * @param destin the destin {@link OutputStream} * @param closeOutputStream */ public static void copyStream(InputStream source, OutputStream destin, Boolean closeOutputStream) { try { int count = 0; byte[] buffer = new byte[FileUtils.BUFFER_SIZE]; while ((count = source.read(buffer, 0, FileUtils.BUFFER_SIZE)) != -1) { destin.write(buffer, 0, count); } } catch (IOException e) { throw new UnexpectedException("Error copying file", e); } finally { if (closeOutputStream) { safeClose(destin); } } } /** * @param source the source {@link InputStream} * @param destin the destin {@link OutputStream} */ public static void copyStream(InputStream source, OutputStream destin) { copyStream(source, destin, true); } /** * @param source the source {@link InputStream} * @return the input stream that can be reset {@link ByteArrayInputStream} */ public static ByteArrayInputStream copy(InputStream source) { ByteArrayOutputStream tmp = new ByteArrayOutputStream(); copyStream(source, tmp, true); return new ByteArrayInputStream(tmp.toByteArray()); } public static File zipFile(String directoryToZipPath) { ZipOutputStream zipOutputStream = null; try { File zipFile = FileUtils.createTempFile(); zipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile))); // Get a list of the files to zip File directoryToZip = new File(directoryToZipPath); zipFileItem(directoryToZipPath, zipOutputStream, directoryToZip, null); return zipFile; } catch (FileNotFoundException e) { throw new UnexpectedException(e); } finally { safeClose(zipOutputStream); } } private static void zipFileItem(String directoryToZipPath, ZipOutputStream zipOutputStream, File fileItem, String parentItemPath) { try { String files[] = fileItem.list(); for (String file : files) { String itemRelativePath = (parentItemPath != null ? parentItemPath + File.separatorChar : "") + file; File itemFile = new File(directoryToZipPath + File.separatorChar + itemRelativePath); if (itemFile.isDirectory()) { FileUtils.zipFileItem(directoryToZipPath, zipOutputStream, itemFile, itemRelativePath); } else { FileInputStream entryInputStream = new FileInputStream(fileItem.getAbsolutePath() + File.separatorChar + file); ZipEntry entry = new ZipEntry(itemRelativePath); zipOutputStream.putNextEntry(entry); FileUtils.copyStream(entryInputStream, zipOutputStream, false); entryInputStream.close(); } } } catch (IOException e) { throw new UnexpectedException(e); } } public static void safeClose(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (IOException e) { LOGGER.warn("Exception thrown when trying to close the closeable", e); } } } /** * Counts the size of a directory recursively (sum of the length of all files). * * @param directory directory to inspect, must not be null * @return size of directory in bytes, 0 if directory is security restricted */ public static long getDirectorySize(File directory) { if (!directory.exists()) { throw new IllegalArgumentException(directory + " does not exist"); } if (!directory.isDirectory()) { throw new IllegalArgumentException(directory + " is not a directory"); } long size = 0; File[] files = directory.listFiles(); if (files == null) { // null if security restricted return 0L; } for (File file : files) { if (file.isDirectory()) { size += getDirectorySize(file); } else { size += file.length(); } } return size; } public static long getFileSize(File file) { if (!file.exists()) { throw new IllegalArgumentException(file + " does not exist"); } return file.length(); } public static float getDirectorySizeInMB(File directory) { return getDirectorySize(directory) / (float)FileUtils.BYTES_TO_MB; } public static float getFileSizeInMB(File file) { return getFileSize(file) / (float)FileUtils.BYTES_TO_MB; } }