2009-01-25 00:08:57 +00:00
|
|
|
|
|
|
|
package net.sourceforge.tuned;
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileFilter;
|
2009-10-20 21:16:34 +00:00
|
|
|
import java.io.FileInputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
2009-02-03 20:36:57 +00:00
|
|
|
import java.util.ArrayList;
|
2009-06-19 22:35:39 +00:00
|
|
|
import java.util.Collection;
|
2009-10-29 01:22:00 +00:00
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.LinkedList;
|
2009-02-03 20:36:57 +00:00
|
|
|
import java.util.List;
|
2009-07-26 16:54:24 +00:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
2009-01-25 00:08:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
public final class FileUtilities {
|
|
|
|
|
2009-10-20 21:16:34 +00:00
|
|
|
public static byte[] readAll(File source) throws IOException {
|
|
|
|
InputStream in = new FileInputStream(source);
|
|
|
|
|
|
|
|
try {
|
|
|
|
byte[] data = new byte[(int) source.length()];
|
|
|
|
|
|
|
|
int position = 0;
|
|
|
|
int read = 0;
|
|
|
|
|
|
|
|
while (position < data.length && (read = in.read(data, position, data.length - position)) >= 0) {
|
|
|
|
position += read;
|
|
|
|
}
|
|
|
|
|
|
|
|
return data;
|
|
|
|
} finally {
|
|
|
|
in.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-26 16:54:24 +00:00
|
|
|
/**
|
|
|
|
* Pattern used for matching file extensions.
|
|
|
|
*
|
|
|
|
* e.g. "file.txt" -> match "txt", ".hidden" -> no match
|
|
|
|
*/
|
2009-08-10 11:46:24 +00:00
|
|
|
public static final Pattern EXTENSION = Pattern.compile("(?<=.[.])\\p{Alnum}+$");
|
2009-07-26 16:54:24 +00:00
|
|
|
|
|
|
|
|
2009-01-25 00:08:57 +00:00
|
|
|
public static String getExtension(File file) {
|
2009-04-07 18:33:05 +00:00
|
|
|
if (file.isDirectory())
|
|
|
|
return null;
|
|
|
|
|
2009-01-25 00:08:57 +00:00
|
|
|
return getExtension(file.getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static String getExtension(String name) {
|
2009-08-10 11:46:24 +00:00
|
|
|
Matcher matcher = EXTENSION.matcher(name);
|
2009-01-25 00:08:57 +00:00
|
|
|
|
2009-07-26 16:54:24 +00:00
|
|
|
if (matcher.find()) {
|
|
|
|
// extension without leading '.'
|
|
|
|
return matcher.group();
|
2009-01-25 00:08:57 +00:00
|
|
|
}
|
|
|
|
|
2009-07-26 16:54:24 +00:00
|
|
|
// no extension
|
2009-01-25 00:08:57 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean hasExtension(File file, String... extensions) {
|
2009-08-10 11:46:24 +00:00
|
|
|
// avoid native call for speed, if possible
|
|
|
|
return hasExtension(file.getName(), extensions) && !file.isDirectory();
|
2009-01-25 00:08:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean hasExtension(String filename, String... extensions) {
|
|
|
|
String extension = getExtension(filename);
|
|
|
|
|
2009-08-10 11:46:24 +00:00
|
|
|
for (String value : extensions) {
|
|
|
|
if ((extension == null && value == null) || (extension != null && extension.equalsIgnoreCase(value)))
|
|
|
|
return true;
|
2009-01-25 00:08:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static String getNameWithoutExtension(String name) {
|
2009-08-10 11:46:24 +00:00
|
|
|
Matcher matcher = EXTENSION.matcher(name);
|
2009-01-25 00:08:57 +00:00
|
|
|
|
2009-07-26 16:54:24 +00:00
|
|
|
if (matcher.find()) {
|
|
|
|
return name.substring(0, matcher.start() - 1);
|
|
|
|
}
|
2009-01-25 00:08:57 +00:00
|
|
|
|
|
|
|
// no extension, return given name
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static String getName(File file) {
|
|
|
|
if (file.isDirectory())
|
|
|
|
return getFolderName(file);
|
|
|
|
|
|
|
|
return getNameWithoutExtension(file.getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static String getFolderName(File file) {
|
|
|
|
String name = file.getName();
|
|
|
|
|
|
|
|
if (!name.isEmpty())
|
|
|
|
return name;
|
|
|
|
|
|
|
|
// file might be a drive (only has a path, but no name)
|
|
|
|
return file.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean containsOnly(Iterable<File> files, FileFilter filter) {
|
|
|
|
for (File file : files) {
|
|
|
|
if (!filter.accept(file))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-02-03 20:36:57 +00:00
|
|
|
|
|
|
|
public static List<File> filter(Iterable<File> files, FileFilter... filters) {
|
|
|
|
List<File> accepted = new ArrayList<File>();
|
|
|
|
|
|
|
|
for (File file : files) {
|
|
|
|
for (FileFilter filter : filters) {
|
|
|
|
if (filter.accept(file)) {
|
|
|
|
accepted.add(file);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return accepted;
|
|
|
|
}
|
|
|
|
|
2009-06-13 09:53:48 +00:00
|
|
|
|
2010-10-23 03:51:19 +00:00
|
|
|
public static List<File> flatten(Iterable<File> roots, int maxDepth) {
|
|
|
|
List<File> files = new ArrayList<File>();
|
|
|
|
|
|
|
|
// unfold/flatten file tree
|
|
|
|
for (File root : roots) {
|
|
|
|
if (root.isDirectory()) {
|
|
|
|
listFiles(root, 0, files, maxDepth);
|
|
|
|
} else {
|
|
|
|
files.add(root);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return files;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-29 01:22:00 +00:00
|
|
|
public static List<File> listPath(File file) {
|
|
|
|
LinkedList<File> nodes = new LinkedList<File>();
|
|
|
|
|
|
|
|
for (File node = file; node != null; node = node.getParentFile()) {
|
|
|
|
nodes.addFirst(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-21 22:39:02 +00:00
|
|
|
public static List<File> listFiles(Iterable<File> folders, int maxDepth) {
|
|
|
|
List<File> files = new ArrayList<File>();
|
|
|
|
|
|
|
|
// collect files from directory tree
|
|
|
|
for (File folder : folders) {
|
|
|
|
listFiles(folder, 0, files, maxDepth);
|
|
|
|
}
|
|
|
|
|
|
|
|
return files;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void listFiles(File folder, int depth, List<File> files, int maxDepth) {
|
|
|
|
if (depth > maxDepth)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (File file : folder.listFiles()) {
|
|
|
|
if (file.isDirectory()) {
|
|
|
|
listFiles(file, depth + 1, files, maxDepth);
|
|
|
|
} else {
|
|
|
|
files.add(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-10 11:46:24 +00:00
|
|
|
/**
|
2009-10-29 01:22:00 +00:00
|
|
|
* Invalid file name characters: \, /, :, *, ?, ", <, >, |, \r and \n
|
2009-08-10 11:46:24 +00:00
|
|
|
*/
|
|
|
|
public static final Pattern ILLEGAL_CHARACTERS = Pattern.compile("[\\\\/:*?\"<>|\\r\\n]");
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-10-29 01:22:00 +00:00
|
|
|
* Strip file name of invalid characters
|
2009-08-10 11:46:24 +00:00
|
|
|
*
|
|
|
|
* @param filename original filename
|
2009-10-29 01:22:00 +00:00
|
|
|
* @return valid file name stripped of invalid characters
|
2009-08-10 11:46:24 +00:00
|
|
|
*/
|
|
|
|
public static String validateFileName(CharSequence filename) {
|
2009-10-29 01:22:00 +00:00
|
|
|
// strip invalid characters from file name
|
2009-08-10 11:46:24 +00:00
|
|
|
return ILLEGAL_CHARACTERS.matcher(filename).replaceAll("");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean isInvalidFileName(CharSequence filename) {
|
2009-10-29 01:22:00 +00:00
|
|
|
// check if file name contains any illegal characters
|
2009-08-10 11:46:24 +00:00
|
|
|
return ILLEGAL_CHARACTERS.matcher(filename).find();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-29 01:22:00 +00:00
|
|
|
public static File validateFileName(File file) {
|
|
|
|
// windows drives (e.g. c:, d:, etc.) are never invalid because name will be an empty string
|
|
|
|
if (!isInvalidFileName(file.getName()))
|
|
|
|
return file;
|
|
|
|
|
|
|
|
// validate file name only
|
|
|
|
return new File(file.getParentFile(), validateFileName(file.getName()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static File validateFilePath(File path) {
|
|
|
|
Iterator<File> nodes = listPath(path).iterator();
|
|
|
|
|
|
|
|
// initialize with root node, keep original root object if possible (so we don't loose the drive on windows)
|
|
|
|
File validatedPath = validateFileName(nodes.next());
|
|
|
|
|
|
|
|
// validate the rest of the path
|
|
|
|
while (nodes.hasNext()) {
|
|
|
|
validatedPath = new File(validatedPath, validateFileName(nodes.next().getName()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return validatedPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean isInvalidFilePath(File path) {
|
|
|
|
// check if file name contains any illegal characters
|
|
|
|
for (File node = path; node != null; node = node.getParentFile()) {
|
|
|
|
if (isInvalidFileName(node.getName()))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-04 23:22:28 +00:00
|
|
|
public static String replacePathSeparators(CharSequence path) {
|
|
|
|
return Pattern.compile("\\s*[\\\\/]+\\s*").matcher(path).replaceAll(" ");
|
2010-02-03 22:51:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-10 11:46:24 +00:00
|
|
|
public static final long KILO = 1024;
|
|
|
|
public static final long MEGA = KILO * 1024;
|
|
|
|
public static final long GIGA = MEGA * 1024;
|
|
|
|
|
|
|
|
|
|
|
|
public static String formatSize(long size) {
|
|
|
|
if (size >= MEGA)
|
|
|
|
return String.format("%,d MB", size / MEGA);
|
|
|
|
else if (size >= KILO)
|
|
|
|
return String.format("%,d KB", size / KILO);
|
|
|
|
else
|
|
|
|
return String.format("%,d Byte", size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-25 00:08:57 +00:00
|
|
|
public static final FileFilter FOLDERS = new FileFilter() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean accept(File file) {
|
|
|
|
return file.isDirectory();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public static final FileFilter FILES = new FileFilter() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean accept(File file) {
|
|
|
|
return file.isFile();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-06-13 09:53:48 +00:00
|
|
|
|
2009-01-25 00:08:57 +00:00
|
|
|
public static class ExtensionFileFilter implements FileFilter {
|
|
|
|
|
|
|
|
private final String[] extensions;
|
|
|
|
|
2009-06-13 09:53:48 +00:00
|
|
|
|
2009-01-25 00:08:57 +00:00
|
|
|
public ExtensionFileFilter(String... extensions) {
|
|
|
|
this.extensions = extensions;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-19 22:35:39 +00:00
|
|
|
public ExtensionFileFilter(Collection<String> extensions) {
|
|
|
|
this.extensions = extensions.toArray(new String[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-25 00:08:57 +00:00
|
|
|
@Override
|
|
|
|
public boolean accept(File file) {
|
|
|
|
return hasExtension(file, extensions);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-13 09:53:48 +00:00
|
|
|
public boolean accept(String name) {
|
|
|
|
return hasExtension(name, extensions);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-30 12:57:09 +00:00
|
|
|
public boolean acceptExtension(String extension) {
|
|
|
|
for (String other : extensions) {
|
|
|
|
if (other.equalsIgnoreCase(extension))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-10 11:46:24 +00:00
|
|
|
public String[] extensions() {
|
|
|
|
return extensions.clone();
|
2009-01-25 00:08:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-13 09:53:48 +00:00
|
|
|
|
2009-01-25 00:08:57 +00:00
|
|
|
/**
|
|
|
|
* Dummy constructor to prevent instantiation.
|
|
|
|
*/
|
|
|
|
private FileUtilities() {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|