/* * Copyright 2012 James Moger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.moxie.utils; import java.io.BufferedInputStream; 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.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; /** * Common file utilities. * * @author James Moger * */ public class FileUtils { public final static long KILOBYTE = 1024L; public final static long MEGABYTE = 1024L*1024L; public final static long GIGABYTE = 1024L*1024L*1024L; /** * Returns the byte content of the specified file. * * @param file * @return the byte content of the file */ public static byte [] readContent(File file) { ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length()); try { FileInputStream fis = new FileInputStream(file); int len = 0; byte [] buffer = new byte[32767]; while ((len = fis.read(buffer)) > -1) { bos.write(buffer, 0, len); } fis.close(); } catch (Throwable t) { System.err.println("Failed to read content of " + file.getAbsolutePath()); t.printStackTrace(); } return bos.toByteArray(); } /** * Returns the string content of the specified file. * * @param file * @param lineEnding * @return the string content of the file */ public static String readContent(File file, String lineEnding) { StringBuilder sb = new StringBuilder(); try { InputStreamReader is = new InputStreamReader(new FileInputStream( file), Charset.forName("UTF-8")); BufferedReader reader = new BufferedReader(is); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); if (lineEnding != null) { sb.append(lineEnding); } } reader.close(); } catch (Throwable t) { System.err.println("Failed to read content of " + file.getAbsolutePath()); t.printStackTrace(); } return sb.toString(); } /** * Returns the string content of the specified file. * * @param file * @param lineEnding * @return the string content of the file */ public static List<String> readLines(File file, String lineEnding) { List<String> lines = new ArrayList<String>(); try { InputStreamReader is = new InputStreamReader(new FileInputStream( file), Charset.forName("UTF-8")); BufferedReader reader = new BufferedReader(is); String line = null; while ((line = reader.readLine()) != null) { lines.add(line); } reader.close(); } catch (Throwable t) { System.err.println("Failed to read content of " + file.getAbsolutePath()); t.printStackTrace(); } return lines; } /** * Writes the string content to the file. * * @param file * @param content */ public static void writeContent(File file, String content) { File tempFile = new File(file.getAbsolutePath() + "." + Long.toHexString(System.currentTimeMillis())); try { file.getAbsoluteFile().getParentFile().mkdirs(); OutputStreamWriter os = new OutputStreamWriter( new FileOutputStream(tempFile), Charset.forName("UTF-8")); BufferedWriter writer = new BufferedWriter(os); writer.append(content); writer.close(); if (file.exists()) { if (!file.delete()) { System.err.println("Failed to delete " + file); } } if (!tempFile.renameTo(file)) { System.err.println("Failed to rename temp file to " + file); } } catch (Throwable t) { System.err.println("Failed to write content of " + file); t.printStackTrace(); } } /** * Writes the string content to the file. * * @param file * @param content */ public static void writeContent(File file, byte [] data) { File tempFile = new File(file.getAbsolutePath() + "." + Long.toHexString(System.currentTimeMillis())); try { file.getAbsoluteFile().getParentFile().mkdirs(); FileOutputStream os = new FileOutputStream(tempFile); os.write(data); os.close(); if (file.exists()) { file.delete(); } tempFile.renameTo(file); } catch (IOException e) { throw new RuntimeException("Error writing to file " + file, e); } } /** * Recursively traverses a folder and its subfolders to calculate the total * size in bytes. * * @param directory * @return folder size in bytes */ public static long folderSize(File directory) { if (directory == null || !directory.exists()) { return -1; } if (directory.isFile()) { return directory.length(); } long length = 0; File [] files = directory.listFiles(); if (files != null) { for (File file : files) { if (file.isFile()) { length += file.length(); } else { length += folderSize(file); } } } return length; } /** * Copies a file or folder (recursively) to a destination folder. * * @param destinationFolder * @param filesOrFolders * @return * @throws FileNotFoundException * @throws IOException */ public static void copy(File destinationFolder, File... filesOrFolders) throws FileNotFoundException, IOException { destinationFolder.mkdirs(); if (filesOrFolders == null) { return; } for (File file : filesOrFolders) { if (file.isDirectory()) { copy(new File(destinationFolder, file.getName()), file.listFiles()); } else if (file.exists()) { File dFile = new File(destinationFolder, file.getName()); BufferedInputStream bufin = null; FileOutputStream fos = null; try { bufin = new BufferedInputStream(new FileInputStream(file)); fos = new FileOutputStream(dFile); int len = 8196; byte[] buff = new byte[len]; int n = 0; while ((n = bufin.read(buff, 0, len)) != -1) { fos.write(buff, 0, n); } } finally { try { bufin.close(); } catch (Throwable t) { } try { fos.close(); } catch (Throwable t) { } } dFile.setLastModified(file.lastModified()); } } } /** * Copies a file to another file. * * @param fromFile * @param toFile * @throws FileNotFoundException * @throws IOException */ public static void copyFile(File fromFile, File toFile) throws FileNotFoundException, IOException { toFile.getParentFile().mkdirs(); BufferedInputStream bufin = null; FileOutputStream fos = null; try { bufin = new BufferedInputStream(new FileInputStream(fromFile)); fos = new FileOutputStream(toFile); int len = 8196; byte[] buff = new byte[len]; int n = 0; while ((n = bufin.read(buff, 0, len)) != -1) { fos.write(buff, 0, n); } } finally { try { bufin.close(); } catch (Throwable t) { } try { fos.close(); } catch (Throwable t) { } } toFile.setLastModified(fromFile.lastModified()); } /** * Delete a file or recursively delete a folder. * * @param fileOrFolder * @return true, if successful */ public static boolean delete(File fileOrFolder) { boolean success = false; if (fileOrFolder.isDirectory()) { File [] files = fileOrFolder.listFiles(); if (files != null) { for (File file : files) { if (file.isDirectory()) { success |= delete(file); } else { success |= file.delete(); } } } } success |= fileOrFolder.delete(); return success; } /** * Java on Linux may only have second resolution * * @param file * @return lastModified rounded to seconds */ public static long getLastModified(File file) { if (file.exists()) { return (file.lastModified()/1000L)*1000L; } return System.currentTimeMillis(); } /** * Determine the relative path between two files. Takes into account * canonical paths, if possible. * * @param basePath * @param path * @return a relative path from basePath to path */ public static String getRelativePath(File basePath, File path) { File exactBase = getExactFile(basePath); File exactPath = getExactFile(path); if (path.getAbsolutePath().startsWith(basePath.getAbsolutePath())) { // absolute base-path match return StringUtils.getRelativePath(basePath.getAbsolutePath(), path.getAbsolutePath()); } else if (exactPath.getPath().startsWith(exactBase.getPath())) { // canonical base-path match return StringUtils.getRelativePath(exactBase.getPath(), exactPath.getPath()); } else if (exactPath.getPath().startsWith(basePath.getAbsolutePath())) { // mixed path match return StringUtils.getRelativePath(basePath.getAbsolutePath(), exactPath.getPath()); } else if (path.getAbsolutePath().startsWith(exactBase.getPath())) { // mixed path match return StringUtils.getRelativePath(exactBase.getPath(), path.getAbsolutePath()); } // no relative relationship return null; } /** * Returns the exact path for a file. This path will be the canonical path * unless an exception is thrown in which case it will be the absolute path. * * @param path * @return the exact file */ public static File getExactFile(File path) { try { return path.getCanonicalFile(); } catch (IOException e) { return path.getAbsoluteFile(); } } /** * Formats a file size as a human-readable string. * @param size * @return human-readable file size */ public static String formatSize(long size) { if (size < 1024) { return size + " bytes"; } double sz = size; String units; double nsz; String format = "0"; if (size >= GIGABYTE) { nsz = sz/GIGABYTE; units = "GB"; format = "0.0"; } else if (size >= MEGABYTE) { nsz = sz/MEGABYTE; units = "MB"; format = "0.0"; } else { nsz = sz/KILOBYTE; units = "KB"; } return new DecimalFormat(format).format(nsz) + " " + units; } }