/***************************************************************************
* Copyright (C) 2008 by H-Store Project *
* Brown University *
* Massachusetts Institute of Technology *
* Yale University *
* *
* Permission is hereby granted, free of charge, to any person obtaining *
* a copy of this software and associated documentation files (the *
* "Software"), to deal in the Software without restriction, including *
* without limitation the rights to use, copy, modify, merge, publish, *
* distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to *
* the following conditions: *
* *
* The above copyright notice and this permission notice shall be *
* included in all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
***************************************************************************/
package edu.brown.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import org.apache.log4j.Logger;
/**
* A bunch of random utility methods for reading/writing files
* @author pavlo
*/
public abstract class FileUtil {
private static final Logger LOG = Logger.getLogger(FileUtil.class);
private static final Pattern EXT_SPLIT = Pattern.compile("\\.");
/**
* Join path segments together into a single file
* This is meant to mimic Python's os.path.join
* @param paths
*/
public static File join(String...paths) {
String fullPath = "";
for (String p : paths) {
if (fullPath.isEmpty() == false) fullPath += File.separator;
fullPath += p;
} // FOR
return new File(fullPath);
}
public static boolean exists(String path) {
if (path == null) return (false);
return (new File(path).exists());
}
public static String realpath(String path) {
File f = new File(path);
String ret = null;
try {
ret = f.getCanonicalPath();
} catch (Exception ex) {
LOG.warn(ex);
}
return (ret);
}
public static String basename(String path) {
return (new File(path)).getName();
}
public static String getExtension(File f) {
if (f != null && f.isFile()) {
String parts[] = EXT_SPLIT.split(f.getName());
if (parts.length > 1) {
return (parts[parts.length - 1]);
}
}
return (null);
}
/**
* Create any directory in the list paths if it doesn't exist
* @param paths
*/
public static void makeDirIfNotExists(String... paths) {
for (String p : paths) {
if (p == null)
continue;
File f = new File(p);
if (f.exists() == false) {
f.mkdirs();
}
} // FOR
}
/**
* Create any directory in the list paths if it doesn't exist
* @param paths
*/
public static void makeDirIfNotExists(File... paths) {
for (File f : paths) {
makeDirIfNotExists(f.getAbsolutePath());
}
}
/**
* Return a File handle to a temporary file location
*
* @param ext
* the suffix of the filename
* @param deleteOnExit
* whether to delete this file after the JVM exits
* @return
*/
public static File getTempFile(String ext, boolean deleteOnExit) {
return getTempFile((String)null, ext, deleteOnExit);
}
public static File getTempFile(String ext) {
return (FileUtil.getTempFile((String)null, ext, false));
}
public static File getTempFile(String prefix, String suffix, boolean deleteOnExit) {
return getTempFile(new File(System.getProperty("java.io.tmpdir")), prefix, suffix, deleteOnExit);
}
public static File getTempFile(File tempDir, String ext, boolean deleteOnExit) {
return getTempFile(tempDir, null, ext, deleteOnExit);
}
public static File getTempFile(File tempDir, String prefix, String suffix, boolean deleteOnExit) {
File tempFile;
if (suffix != null && suffix.startsWith(".") == false)
suffix = "." + suffix;
if (prefix == null)
prefix = "hstore";
try {
tempFile = File.createTempFile(prefix, suffix, tempDir);
if (deleteOnExit)
tempFile.deleteOnExit();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return (tempFile);
}
/**
* Unsafely create a temporary directory Yes I said that this was unsafe. I
* don't care...
* @return
*/
public static File getTempDirectory() {
return getTempDirectory(null);
}
public static File getTempDirectory(String suffix) {
final File temp = FileUtil.getTempFile(suffix);
if (!(temp.delete())) {
throw new RuntimeException("Could not delete temp file: " + temp.getAbsolutePath());
} else if (!(temp.mkdir())) {
throw new RuntimeException("Could not create temp directory: " + temp.getAbsolutePath());
}
return (temp);
}
public static File writeStringToFile(String file_path, String content) throws IOException {
return (FileUtil.writeStringToFile(new File(file_path), content));
}
public static File writeStringToFile(File file, String content) throws IOException {
FileWriter writer = new FileWriter(file);
writer.write(content);
writer.flush();
writer.close();
return (file);
}
/**
* Write the given string to a temporary file Will not delete the file after
* the JVM exits
*
* @param content
* @return
*/
public static File writeStringToTempFile(String content) {
return (writeStringToTempFile(content, "tmp", false));
}
/**
* Write the given string to a temporary file with the given extension as
* the suffix Will not delete the file after the JVM exits
*
* @param content
* @param ext
* @return
*/
public static File writeStringToTempFile(String content, String ext) {
return (writeStringToTempFile(content, ext, false));
}
/**
* Write the given string to a temporary file with the given extension as
* the suffix If deleteOnExit is true, then the file will be removed when
* the JVM exits
*
* @param content
* @param ext
* @param deleteOnExit
* @return
*/
public static File writeStringToTempFile(String content, String ext, boolean deleteOnExit) {
File tempFile = FileUtil.getTempFile(ext, deleteOnExit);
try {
FileUtil.writeStringToFile(tempFile, content);
} catch (Exception e) {
throw new RuntimeException(e);
}
return tempFile;
}
public static String readFile(File path) {
return (readFile(path.getAbsolutePath()));
}
public static String readFile(String path) {
StringBuilder buffer = new StringBuilder();
try {
BufferedReader in = FileUtil.getReader(path);
while (in.ready()) {
buffer.append(in.readLine()).append("\n");
} // WHILE
in.close();
} catch (IOException ex) {
throw new RuntimeException("Failed to read file contents from '" + path + "'", ex);
}
return (buffer.toString());
}
/**
* Creates a BufferedReader for the given input path Can handle both gzip
* and plain text files
*
* @param path
* @return
* @throws IOException
*/
public static BufferedReader getReader(String path) throws IOException {
return (FileUtil.getReader(new File(path)));
}
/**
* Creates a BufferedReader for the given input path Can handle both gzip
* and plain text files
*
* @param file
* @return
* @throws IOException
*/
public static BufferedReader getReader(File file) throws IOException {
if (!file.exists()) {
throw new IOException("The file '" + file + "' does not exist");
}
BufferedReader in = null;
if (file.getPath().endsWith(".gz")) {
FileInputStream fin = new FileInputStream(file);
GZIPInputStream gzis = new GZIPInputStream(fin);
in = new BufferedReader(new InputStreamReader(gzis));
LOG.debug("Reading in the zipped contents of '" + file.getName() + "'");
} else {
in = new BufferedReader(new FileReader(file));
LOG.debug("Reading in the contents of '" + file.getName() + "'");
}
return (in);
}
public static byte[] readBytesFromFile(String path) throws IOException {
File file = new File(path);
FileInputStream in = new FileInputStream(file);
// Create the byte array to hold the data
long length = file.length();
byte[] bytes = new byte[(int) length];
LOG.debug("Reading in the contents of '" + file.getAbsolutePath() + "'");
// Read in the bytes
int offset = 0;
int numRead = 0;
while ((offset < bytes.length) && ((numRead = in.read(bytes, offset, bytes.length - offset)) >= 0)) {
offset += numRead;
} // WHILE
if (offset < bytes.length) {
throw new IOException("Failed to read the entire contents of '" + file.getName() + "'");
}
in.close();
return (bytes);
}
/**
* Recursively delete all of the contents of the given directory
* @param path
* @return
*/
public static boolean deleteDirectory(File path) {
if (path.exists()) {
File[] files = path.listFiles();
for (File f : files) {
if (f.isDirectory()) {
deleteDirectory(f);
} else {
f.delete();
}
}
}
return path.delete();
}
/**
* Find the path to a directory below our current location in the source
* tree Throws a RuntimeException if we go beyond our repository checkout
*
* @param dirName
* @return
* @throws IOException
*/
public static File findDirectory(String dirName) throws IOException {
return (FileUtil.find(dirName, new File(".").getCanonicalFile(), true).getCanonicalFile());
}
/**
* Find the path to a directory below our current location in the source
* tree Throws a RuntimeException if we go beyond our repository checkout
*
* @param dirName
* @return
* @throws IOException
*/
public static File findFile(String fileName) throws IOException {
return (FileUtil.find(fileName, new File(".").getCanonicalFile(), false).getCanonicalFile());
}
private static final File find(String name, File current, boolean isdir) throws IOException {
LOG.debug("Find Current Location = " + current);
boolean has_git = false;
for (File file : current.listFiles()) {
if (file.getCanonicalPath().endsWith(File.separator + name) && file.isDirectory() == isdir) {
return (file);
// Make sure that we don't go to far down...
} else if (file.getCanonicalPath().endsWith(File.separator + ".git")) {
has_git = true;
}
} // FOR
// If we didn't see an .svn directory, then we went too far down
if (!has_git)
throw new RuntimeException("Unable to find directory '" + name + "' [last_dir=" + current.getAbsolutePath() + "]");
File next = new File(current.getCanonicalPath() + File.separator + "..");
return (FileUtil.find(name, next, isdir));
}
/**
* Returns a list of all the files in a directory whose name starts with the
* provided prefix
*
* @param dir
* @param filePrefix
* @return
* @throws IOException
*/
public static List<File> getFilesInDirectory(final File dir, final String filePrefix) throws IOException {
assert (dir.isDirectory()) : "Invalid search directory path: " + dir;
FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return (name.startsWith(filePrefix));
}
};
return (Arrays.asList(dir.listFiles(filter)));
}
}