java-commons/src/main/java/io/gitlab/jfronny/commons/io/JFiles.java

177 lines
7.5 KiB
Java

package io.gitlab.jfronny.commons.io;
import io.gitlab.jfronny.commons.serialize.Serializer;
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class JFiles {
public static void clearDirectory(Path directory) throws IOException {
clearDirectory(directory, p -> true);
}
public static void clearDirectory(Path directory, Predicate<Path> shouldDelete) throws IOException {
if (!Files.exists(directory)) return;
try {
listTo(directory, p -> {
if (Files.isDirectory(p)) {
try {
if (shouldDelete.test(p))
deleteRecursive(p, shouldDelete);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
else {
try {
if (shouldDelete.test(p))
Files.delete(p);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
} catch (Throwable t) {
throw new IOException("Could not clear directory", t);
}
}
public static void deleteRecursive(Path path) throws IOException {
deleteRecursive(path, p -> true);
}
public static void deleteRecursive(Path path, Predicate<Path> shouldDelete) throws IOException {
if (Files.isDirectory(path)) {
Files.walkFileTree(path, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
FileVisitResult fv = super.visitFile(file, attrs);
if (fv != FileVisitResult.CONTINUE) return fv;
if (shouldDelete.test(file))
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
FileVisitResult fv = super.postVisitDirectory(dir, exc);
if (fv != FileVisitResult.CONTINUE) return fv;
if (shouldDelete.test(dir) && list(dir).isEmpty()) {
Files.delete(dir);
}
return FileVisitResult.CONTINUE;
}
});
}
else Files.delete(path);
}
@Deprecated
public static void copyContent(Path source, Path destination) throws IOException {
copyRecursive(source, destination);
}
@Deprecated
public static void copyContent(Path source, Path target, CopyOption... copyOptions) throws IOException {
copyRecursive(source, target, copyOptions);
}
/**
* If the source is a file, copy it to the target. If it is a directory, create the target directory if it doesn't exist and copy the source directories content there
* @param source The path to copy from
* @param destination The path to copy to
* @throws IOException Something went wrong
*/
public static void copyRecursive(Path source, Path destination) throws IOException {
copyRecursive(source, destination, StandardCopyOption.COPY_ATTRIBUTES);
}
/**
* If the source is a file, copy it to the destination. If it is a directory, create the destination directory if it doesn't exist and copy the source directories' content there
* @param source The path to copy from
* @param destination The path to copy to
* @param copyOptions Copy options to use
* @throws IOException Something went wrong
*/
public static void copyRecursive(Path source, Path destination, CopyOption... copyOptions) throws IOException {
boolean replaceExisting = Arrays.asList(copyOptions).contains(StandardCopyOption.REPLACE_EXISTING);
if (Files.isDirectory(source)) {
Files.createDirectories(destination);
listTo(source, sourceResolved -> {
Path targetResolved = destination.resolve(sourceResolved.getFileName().toString());
if (Files.exists(destination)) {
if (!replaceExisting) return;
if (!Files.isDirectory(sourceResolved)) Files.delete(destination);
}
copyRecursive(sourceResolved, targetResolved, copyOptions);
});
} else if (Files.exists(source)) {
if (destination.getParent() != null) Files.createDirectories(destination.getParent());
if (!Files.exists(destination) || replaceExisting) Files.copy(source, destination, copyOptions);
} else throw new FileNotFoundException(source.toString());
}
public static List<Path> list(Path directory) throws IOException {
try (Stream<Path> sp = Files.list(directory)) {
return sp.toList();
}
}
public static List<Path> list(Path directory, Predicate<Path> entryPredicate) throws IOException {
try (Stream<Path> sp = Files.list(directory); Stream<Path> fi = sp.filter(entryPredicate)) {
return fi.toList();
}
}
public static String[] listNames(Path directory) throws IOException {
try (Stream<Path> sp = Files.list(directory)) {
return sp
.map(p -> Files.isDirectory(p) ? p.getFileName().toString() + "/" : p.getFileName().toString())
.toArray(String[]::new);
}
}
public static <TEx extends Exception> void listTo(Path directory, ThrowingConsumer<Path, TEx> consumer) throws IOException, TEx {
try (Stream<Path> sp = Files.list(directory)) {
for (Path path : sp.toList()) consumer.accept(path);
}
}
public static <T> T readObject(Path file, Type type) throws IOException {
try (BufferedReader br = Files.newBufferedReader(file)) {
return Serializer.getInstance().deserialize(br, type);
}
}
public static <T> T readObject(Path file, Class<T> type) throws IOException {
try (BufferedReader br = Files.newBufferedReader(file)) {
return Serializer.getInstance().deserialize(br, type);
}
}
public static void writeObject(Path file, Object object) throws IOException {
try (BufferedWriter bw = Files.newBufferedWriter(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
Serializer.getInstance().serialize(object, bw);
}
}
private static final Map<Path, MultiAccessFileSystem> zipFsCache = new HashMap<>();
public static FileSystem openZipFile(Path zip, boolean create, @Nullable ClassLoader classLoader) throws IOException, URISyntaxException {
synchronized (zipFsCache) {
if (!zipFsCache.containsKey(zip) || zipFsCache.get(zip).isClosed()) {
URI fileUri = zip.toUri();
zipFsCache.put(zip, MultiAccessFileSystem.create(new URI("jar:" + fileUri.getScheme(), fileUri.getPath(), null), create ? Map.of("create", "true") : Map.of(), classLoader));
}
return zipFsCache.get(zip).createLens();
}
}
}