org.pepsoft.util.FileUtils Maven / Gradle / Ivy
The newest version!
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.util;
import org.jetbrains.annotations.NonNls;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.*;
import java.util.function.Consumer;
import static com.google.common.base.Strings.isNullOrEmpty;
/**
*
* @author pepijn
*/
@SuppressWarnings("ResultOfMethodCallIgnored") // We don't care
public class FileUtils {
private FileUtils() {
// Prevent instantiation
}
public static Checksum getMD5(File file) throws IOException {
try {
MessageDigest md5Digest = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[BUFFER_SIZE];
try (FileInputStream in = new FileInputStream(file)) {
int read;
while ((read = in.read(buffer)) != -1) {
md5Digest.update(buffer, 0, read);
}
}
return new Checksum(md5Digest.digest());
} catch (NoSuchAlgorithmException e) {
// MD5 is among the minimally required algorithms to be supported by
// a Java VM
throw new InternalError("MD5 message digest not supported by Java runtime");
}
}
public static String load(File file, Charset charset) throws IOException {
long length = file.length();
if (length > Integer.MAX_VALUE) {
throw new UnsupportedOperationException("File too large (" + length + " bytes)");
}
StringBuilder sb = new StringBuilder((int) length);
try (InputStreamReader in = new InputStreamReader(new BufferedInputStream(new FileInputStream(file)), charset)) {
char[] buffer = new char[BUFFER_SIZE];
int read;
while ((read = in.read(buffer)) != -1) {
sb.append(buffer, 0, read);
}
}
return sb.toString();
}
public static String load(InputStream inputStream, Charset charset) throws IOException {
StringBuilder sb = new StringBuilder();
try (InputStreamReader in = new InputStreamReader(new BufferedInputStream(inputStream), charset)) {
char[] buffer = new char[BUFFER_SIZE];
int read;
while ((read = in.read(buffer)) != -1) {
sb.append(buffer, 0, read);
}
}
return sb.toString();
}
/**
* Recursively copy a directory including all contents.
*
* @param dir The directory to copy. Must exist.
* @param destDir The directory into which to copy the contents of
* {@code dir}. Must not exist yet and will be created.
* @throws IOException If there is an I/O error while performing the copy.
*/
public static void copyDir(File dir, File destDir) throws IOException {
if (! dir.isDirectory()) {
throw new IllegalArgumentException("Source directory " + dir + " does not exist or is not a directory");
}
if (destDir.isDirectory()) {
throw new IllegalStateException("Destination directory " + destDir + " already exists");
}
if (! destDir.mkdirs()) {
throw new IOException("Could not create " + destDir);
}
File[] files = dir.listFiles();
//noinspection ConstantConditions // Guaranteed by precondition check at start
for (File file: files) {
if (file.isDirectory()) {
copyDir(file, new File(destDir, file.getName()));
} else if (file.isFile()) {
copyFileToDir(file, destDir);
} else {
logger.warn("Not copying " + file + "; not a regular file or directory");
}
}
final long lastModified = dir.lastModified();
if (lastModified > 0) {
destDir.setLastModified(lastModified);
}
}
/**
* Copy a file to another file.
*
* @param file The file to copy.
* @param destFile The file to copy the file to. If {@code overwrite}
* is {@code false} it must not exist yet. In either
* case it may not be an existing directory.
* @param overwrite Whether {@code destFile} should be overwritten if
* it already exists. If this is false and the file does
* already exist an {@link IllegalStateException} will be
* thrown.
* @throws IOException If there is an I/O error while performing the copy.
* @throws IllegalStateException If {@code overwrite} was
* {@code false} and {@code destFile} already existed.
*/
public static void copyFileToFile(File file, File destFile, boolean overwrite) throws IOException {
if ((! overwrite) && destFile.isFile()) {
throw new IllegalStateException("Destination file " + destFile + " already exists");
}
if (destFile.isDirectory()) {
throw new IllegalStateException("Destination file is an existing directory");
}
StreamUtils.copy(new FileInputStream(file), new FileOutputStream(destFile));
final long lastModified = file.lastModified();
if (lastModified > 0) {
destFile.setLastModified(lastModified);
}
}
/**
* Copy a file to another directory.
*
* @param file The file to copy.
* @param destDir The directory to copy the file into, using the same name
* as the source file.
* @throws IOException If there is an I/O error while performing the copy.
*/
public static void copyFileToDir(File file, File destDir) throws IOException {
try {
copyFileToDir(file, destDir, null);
} catch (ProgressReceiver.OperationCancelled e) {
throw new InternalError();
}
}
/**
* Copy a file to another directory with optional progress reporting.
*
* @param file The file to copy.
* @param destDir The directory to copy the file into, using the same name
* as the source file.
* @param progressReceiver The progress receiver to report copying progress
* to. May be {@code null}.
* @throws IOException If there is an I/O error while performing the copy.
*/
public static void copyFileToDir(File file, File destDir, ProgressReceiver progressReceiver) throws IOException, ProgressReceiver.OperationCancelled {
File destFile = new File(destDir, file.getName());
if (destFile.isFile()) {
throw new IllegalStateException("Destination file " + destFile + " already exists");
}
StreamUtils.copy(new FileInputStream(file), new FileOutputStream(destFile), progressReceiver, file.length());
final long lastModified = file.lastModified();
if (lastModified > 0) {
destFile.setLastModified(lastModified);
}
}
/**
* Recursively delete a directory and all its contents.
*
* @param dir The directory to delete.
* @return {@code true} if and only if the directory is successfully deleted; {@code false} otherwise
*/
public static boolean deleteDir(File dir) {
if (! dir.isDirectory()) {
throw new IllegalArgumentException(dir + " does not exist or is not a directory");
}
File[] contents = dir.listFiles();
//noinspection ConstantConditions // Guaranteed by precondition check at start
for (File file: contents) {
if (file.isDirectory()) {
deleteDir(file);
} else {
file.delete();
}
}
return dir.delete();
}
/**
* Recursively delete all contents of a directory.
*
* @param dir The directory to empty.
* @return {@code true} if and only if all contents of the directory
* were successfully deleted; {@code false} otherwise
*/
public static boolean emptyDir(File dir) {
if (! dir.isDirectory()) {
throw new IllegalArgumentException(dir + " does not exist or is not a directory");
}
boolean success = true;
File[] contents = dir.listFiles();
//noinspection ConstantConditions // Guaranteed by precondition check at start
for (File file: contents) {
if (file.isDirectory()) {
success &= deleteDir(file);
} else {
success &= file.delete();
}
}
return success;
}
/**
* Sanitises a filename by replacing characters which are illegal for
* Windows, Linux or Mac OS filenames with underscores and enforcing other
* rules.
*
* @param filename The filename to sanitise.
* @return The sanitised filename.
*/
public static String sanitiseName(@NonNls String filename) {
if (isNullOrEmpty(filename)) {
return filename;
}
StringBuilder sb = new StringBuilder(filename.length());
// Replace illegal characters for Windows, Linux or Mac OS with
// underscores
for (char c: filename.toCharArray()) {
if ((c < 32) || (ILLEGAL_CHARS.indexOf(c) != -1)) {
sb.append(REPLACEMENT_CHAR);
} else {
sb.append(c);
}
}
// Windows can't cope with filenames which end with spaces or periods
if ((sb.charAt(sb.length() - 1) == '.') || (sb.charAt(sb.length() - 1) == ' ')) {
sb.setCharAt(sb.length() - 1, REPLACEMENT_CHAR);
}
// Make sure the name doesn't start with a Windows reserved name, by
// changing the third character to an underscore if necessary
String uppercaseVersion = sb.toString().toUpperCase();
for (String reservedName: RESERVED_NAMES) {
if (uppercaseVersion.startsWith(reservedName)
&& ((uppercaseVersion.length() == reservedName.length())
|| (uppercaseVersion.charAt(reservedName.length()) == '.'))) {
sb.setCharAt(2, REPLACEMENT_CHAR);
break;
}
}
return sb.toString();
}
/**
* Checks if a {@code File} is really a {@code java.io.File}, and
* if not converts it to one using {@link File#getAbsolutePath()}.
*
* @param file The file to absolutise. May be {@code null}.
* @return A file with the same absolute path as the input and guaranteed to
* be of class {@code java.io.File}, or {@code null} if the input was
* {@code null}.
*/
public static File absolutise(File file) {
return ((file != null) && (file.getClass() != File.class))
? new File(file.getAbsolutePath())
: file;
}
/**
* Ensures that a collection of {@link File}s only contains instances of
* {@code java.io.File} and not subclasses, by converting subclasses
* using {@link #absolutise(File)}. The collection is transformed in-place
* if possible; otherwise a new collection with the same basic
* characteristics is created.
*
* @param collection The collection to transform.
* @param The type of collection.
* @return Either the same collection, transformed in-place, or a new
* collection of the same basic type as the input containing the
* transformed results.
*/
@SuppressWarnings("unchecked") // Guaranteed by code
public static > T absolutise(T collection) {
if (collection == null) {
return null;
} else if (collection instanceof List) {
for (ListIterator i = ((List) collection).listIterator(); i.hasNext(); ) {
final File file = i.next();
try {
i.set(absolutise(file));
} catch (UnsupportedOperationException e) {
final Collection newCollection;
if (collection instanceof RandomAccess) {
newCollection = new ArrayList<>(collection.size());
} else {
newCollection = new LinkedList<>();
}
for (File file2: collection) {
newCollection.add(absolutise(file2));
}
return (T) newCollection;
}
}
return collection;
} else {
final Collection newCollection;
if (collection instanceof SortedSet) {
newCollection = new TreeSet<>();
} else if (collection instanceof Set) {
newCollection = new HashSet<>(collection.size());
} else {
newCollection = new ArrayList<>(collection.size());
}
for (File file: collection) {
newCollection.add(absolutise(file));
}
return (T) newCollection;
}
}
/**
* Ensures that a map with {@link File}s as keys and/or values only contains
* instances of {@code java.io.File} and not subclasses, by converting
* subclasses using {@link #absolutise(File)}. The map is transformed
* in-place if possible; otherwise a new map with the same basic
* characteristics is created.
*
* @param map The map to transform.
* @param The type of map.
* @return Either the same map, transformed in-place, or a new map of the
* same basic type as the input containing the transformed results.
*/
@SuppressWarnings("unchecked") // Guaranteed by code
public static > T absolutise(T map) {
if (map == null) {
return null;
}
for (Map.Entry
© 2015 - 2025 Weber Informatics LLC | Privacy Policy