/*
You may freely copy, distribute, modify and use this class as long
as the original author attribution remains intact. See message
below.
Copyright (C) 2003 Christian Pesch. All Rights Reserved.
*/
package slash.metamusic.util;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Some useful methods to create and manipulate File objects
*
* @author Christian Pesch
* @version $Id: Files.java 942 2007-01-10 17:11:12Z cpesch $
*/
public class Files {
/**
* Returns the extension of the file, which are the characters
* behind the last dot in the file name.
*
* @param file the file to find the extension
*/
public static String getExtension(File file) {
return getExtension(file.getName());
}
/**
* Returns the extension of a file name, which are the characters
* behind the last dot in the file name.
*
* @param name the file name to find the extension
*/
public static String getExtension(String name) {
int index = name.lastIndexOf(".");
if (index == -1)
return "";
return name.substring(index + 1, name.length());
}
/**
* Add the given extension to the given file name, even if
* there is already one.
*
* @param fileName the file name to add the extension to
* @param extension the extension to add to the file name
* @return the file name with the added extension
*/
public static String addExtension(String fileName, String extension) {
return fileName + "." + extension;
}
/**
* Remove the extension of the given file name, if there is any.
*
* @param fileName the file name to remove the extension
* @return the file name without an extension
*/
public static String removeExtension(String fileName) {
String extension = getExtension(fileName);
return extension.length() > 0 ? fileName.substring(0, fileName.length() - extension.length() - 1) : fileName;
}
/**
* Replace the extension of the given file name with the
* given extension.
*
* @param fileName the file name to replace the extension
* @param extension the new extension for the file name
* @return the file name with the given extension
*/
public static String replaceExtension(String fileName, String extension) {
String withoutExtension = removeExtension(fileName);
String withExtension = withoutExtension + "." + extension;
return withExtension;
}
/**
* Tries to rename the given file with the new extension
*
* @param file the file to rename
* @param extension the new extension for the file
* @return true if the file was successfully renamed
*/
public static boolean setExtension(File file, String extension) {
String oldName = file.getName();
String newName = replaceExtension(oldName, extension);
return file.renameTo(new File(file.getParentFile(), newName));
}
/**
* Replace the slash characters in the string with the
* plattform-specific File.separatorChar.
*
* @param string the string to operate on
* @return a string, where slash characters "/" are replaced with File.separatorChar
* @see File#separatorChar
*/
public static String replaceSeparators(String string) {
return string.replace('/', File.separatorChar);
}
/**
* Append a slash character "/" to the string if the string
* does not end with a slash.
*
* @param string the string to operate on
* @return a string where the last character is a slash character "/"
*/
public static String appendSlash(String string) {
string = replaceSeparators(string);
if (!string.endsWith(File.separator))
string += File.separatorChar;
return string;
}
/**
* Collects files/directories with the given extension in the given
* set. If path is a directory, it recursively descends the directory
* tree. If no extension is given, all files are collected.
*
* @param path the path to collect files below
* @param collectDirectories decides whether directories are collected
* @param collectFiles decides whether file are collected
* @param extension the extension in lower case
* @param set the set to add hits to
*/
private static void recursiveCollect(File path,
final boolean collectDirectories,
final boolean collectFiles,
final String extension,
final Set<File> set) {
if (path.isFile()) {
if (collectFiles &&
(extension == null || getExtension(path).toLowerCase().equals(extension)))
set.add(path);
} else {
if (collectDirectories)
set.add(path);
path.listFiles(new FileFilter() {
public boolean accept(File file) {
recursiveCollect(file, collectDirectories, collectFiles, extension, set);
return true;
}
});
}
}
/**
* Collects files below the given path with the given extension.
* If path is a directory, the collection recursively descends the
* directory tree. The extension comparison is case insensitive
*
* @param path the path to collect files below
* @param extension the case insensitively compare extension
* @return the list of files found below the given path and
* with the given extension
*/
public static List<File> collectFiles(File path, String extension) {
Set<File> set = new TreeSet<File>();
extension = extension != null ? extension.toLowerCase() : null;
recursiveCollect(path, false, true, extension, set);
return new ArrayList<File>(set);
}
/**
* Collects all files below the given path. If path is a directory,
* the collection recursively descends the directory tree.
*
* @param path the path to collect files below
* @return the list of files found below the given path
*/
public static List<File> collectFiles(File path) {
return collectFiles(path, null);
}
/**
* Collects all directories below the given path. If path is a directory,
* the collection recursively descends the directory tree.
*
* @param path the path to collect directories below
* @return the list of directories found below the given path
*/
public static List<File> collectDirectories(File path) {
Set<File> set = new TreeSet<File>();
recursiveCollect(path, true, false, null, set);
return new ArrayList<File>(set);
}
public static File findExistingPath(File path) {
while (path != null && !path.exists()) {
path = path.getParentFile();
}
return path != null && path.exists() ? path : null;
}
/**
* Relativizes the given file to the given path.
* <p/>
* Note, that this currently just strips off a prefix.
*
* @param path the path to relativize to
* @param file the file to relativize
* @return the relativized path for the given file
*/
public static String relativize(String path, String file) {
if (path == null)
return file;
path = Files.replaceSeparators(new File(path).getAbsolutePath());
file = Files.replaceSeparators(new File(file).getAbsolutePath());
if (file.startsWith(path))
file = file.substring(path.length() + 1);
return file;
}
/**
* Copies the given source file to the given destination file.
*
* @param source the source file to copy
* @param destination where to copy the source to
* @return true, if the source has been copied to the destination
*/
public static boolean copy(File source, File destination) throws IOException {
FileInputStream in = new FileInputStream(source);
FileOutputStream out = new FileOutputStream(destination);
InputOutput inputOutput = new InputOutput(in, out);
inputOutput.start();
inputOutput.close();
return true;
}
/**
* Deletes all files and directories below the given path. If path is a directory,
* the collection recursively descends the directory tree.
*
* @param path the path to delete files and directories below
* @return if the given path has been deleted
*/
public static boolean delete(File path) {
if (path.exists()) {
File[] files = path.listFiles();
for (File file : files) {
if (file.isDirectory()) {
delete(file);
} else {
file.delete();
}
}
}
return path.delete();
}
/**
* Deletes all files and directories below the given path. If path is a directory,
* the collection recursively descends the directory tree.
*
* @param path the path to delete files and directories below
* @return if the given path has been deleted
*/
public static boolean delete(String path) {
return delete(new File(path));
}
}