2021-12-23 10:42:24 +00:00
|
|
|
package com.onthegomap.planetiler.util;
|
2021-05-01 20:40:44 +00:00
|
|
|
|
|
|
|
import java.io.IOException;
|
2021-09-10 00:46:20 +00:00
|
|
|
import java.io.UncheckedIOException;
|
2021-05-01 20:40:44 +00:00
|
|
|
import java.nio.file.FileSystem;
|
|
|
|
import java.nio.file.Files;
|
2021-05-04 12:02:22 +00:00
|
|
|
import java.nio.file.NoSuchFileException;
|
2021-05-01 20:40:44 +00:00
|
|
|
import java.nio.file.Path;
|
2021-05-04 10:17:10 +00:00
|
|
|
import java.util.Comparator;
|
2021-05-01 20:40:44 +00:00
|
|
|
import java.util.stream.Stream;
|
|
|
|
import java.util.stream.StreamSupport;
|
2021-09-10 00:46:20 +00:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
2021-05-01 20:40:44 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Convenience methods for working with files on disk.
|
|
|
|
*/
|
2021-05-01 20:40:44 +00:00
|
|
|
public class FileUtils {
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
|
|
|
|
|
2022-03-09 02:08:03 +00:00
|
|
|
private FileUtils() {}
|
2021-05-01 20:40:44 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Returns a stream that lists all files in {@code fileSystem}. */
|
2021-05-01 20:40:44 +00:00
|
|
|
public static Stream<Path> walkFileSystem(FileSystem fileSystem) {
|
|
|
|
return StreamSupport.stream(fileSystem.getRootDirectories().spliterator(), false)
|
|
|
|
.flatMap(rootDirectory -> {
|
|
|
|
try {
|
|
|
|
return Files.walk(rootDirectory);
|
|
|
|
} catch (IOException e) {
|
2021-09-10 00:46:20 +00:00
|
|
|
LOGGER.error("Unable to walk " + rootDirectory + " in " + fileSystem, e);
|
|
|
|
return Stream.empty();
|
2021-05-01 20:40:44 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Returns true if {@code path} ends with ".extension" (case-insensitive). */
|
2021-05-01 20:40:44 +00:00
|
|
|
public static boolean hasExtension(Path path, String extension) {
|
|
|
|
return path.toString().toLowerCase().endsWith("." + extension.toLowerCase());
|
|
|
|
}
|
2021-05-04 10:17:10 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Returns the size of {@code path} as a file, or 0 if missing/inaccessible. */
|
2021-05-04 10:17:10 +00:00
|
|
|
public static long fileSize(Path path) {
|
|
|
|
try {
|
|
|
|
return Files.size(path);
|
|
|
|
} catch (IOException e) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Returns the directory usage of all files until {@code path} or 0 if missing/inaccessible. */
|
2021-05-04 10:17:10 +00:00
|
|
|
public static long directorySize(Path path) {
|
|
|
|
try {
|
|
|
|
return Files.walk(path)
|
|
|
|
.filter(Files::isRegularFile)
|
|
|
|
.mapToLong(FileUtils::fileSize)
|
|
|
|
.sum();
|
|
|
|
} catch (IOException e) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Returns the size of a directory or file at {@code path} or 0 if missing/inaccessible. */
|
2021-05-04 10:17:10 +00:00
|
|
|
public static long size(Path path) {
|
|
|
|
return Files.isDirectory(path) ? directorySize(path) : fileSize(path);
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Deletes a file if it exists or fails silently if it doesn't. */
|
2021-05-04 10:17:10 +00:00
|
|
|
public static void deleteFile(Path path) {
|
|
|
|
try {
|
|
|
|
Files.deleteIfExists(path);
|
|
|
|
} catch (IOException e) {
|
2021-09-10 00:46:20 +00:00
|
|
|
LOGGER.error("Unable to delete " + path, e);
|
2021-05-04 10:17:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Deletes all files under a directory and fails silently if it doesn't exist. */
|
2021-05-04 10:17:10 +00:00
|
|
|
public static void deleteDirectory(Path path) {
|
|
|
|
try {
|
|
|
|
Files.walk(path)
|
|
|
|
.sorted(Comparator.reverseOrder())
|
|
|
|
.forEach(FileUtils::deleteFile);
|
2021-05-04 12:02:22 +00:00
|
|
|
} catch (NoSuchFileException e) {
|
|
|
|
// this is OK, file doesn't exist, so can't walk
|
2021-05-04 10:17:10 +00:00
|
|
|
} catch (IOException e) {
|
2021-09-10 00:46:20 +00:00
|
|
|
LOGGER.error("Unable to delete " + path, e);
|
2021-05-04 10:17:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Deletes a file or directory recursively, failing silently if missing. */
|
2021-05-04 10:17:10 +00:00
|
|
|
public static void delete(Path path) {
|
|
|
|
if (Files.isDirectory(path)) {
|
|
|
|
deleteDirectory(path);
|
|
|
|
} else {
|
|
|
|
deleteFile(path);
|
|
|
|
}
|
|
|
|
}
|
2021-08-05 01:22:20 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Moves a file.
|
|
|
|
*
|
|
|
|
* @throws UncheckedIOException if an error occurs
|
|
|
|
*/
|
|
|
|
public static void move(Path from, Path to) {
|
|
|
|
try {
|
|
|
|
Files.move(from, to);
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new UncheckedIOException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensures a directory and all parent directories exists.
|
|
|
|
*
|
|
|
|
* @throws IllegalStateException if an error occurs
|
|
|
|
*/
|
2021-08-22 09:37:57 +00:00
|
|
|
public static void createDirectory(Path path) {
|
|
|
|
try {
|
|
|
|
Files.createDirectories(path);
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new IllegalStateException("Unable to create directories " + path, e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Ensures all parent directories of {@code path} exist.
|
|
|
|
*
|
|
|
|
* @throws IllegalStateException if an error occurs
|
|
|
|
*/
|
2021-08-05 01:22:20 +00:00
|
|
|
public static void createParentDirectories(Path path) {
|
|
|
|
try {
|
|
|
|
if (Files.isDirectory(path)) {
|
|
|
|
Files.createDirectories(path);
|
|
|
|
} else {
|
2022-03-03 12:25:24 +00:00
|
|
|
Path parent = path.getParent();
|
|
|
|
if (parent != null) {
|
|
|
|
Files.createDirectories(parent);
|
|
|
|
}
|
2021-08-05 01:22:20 +00:00
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new IllegalStateException("Unable to create parent directories " + path, e);
|
|
|
|
}
|
|
|
|
}
|
2021-09-10 00:46:20 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempts to delete the file located at {@code path} on normal JVM exit.
|
|
|
|
*/
|
|
|
|
public static void deleteOnExit(Path path) {
|
|
|
|
path.toFile().deleteOnExit();
|
|
|
|
}
|
2021-05-01 20:40:44 +00:00
|
|
|
}
|