package melnorme.lang.utils; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Enumeration; import java.util.function.Function; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import melnorme.utilbox.misc.Location; /** * Miscellaneous utils relating to {@link File}'s. * The semantics of these util methods may not be robust or precise enough to be used outside of test code. */ public class MiscFileUtils { public static File getFile(File file, String... segments) { for (String segment : segments) { assertTrue(segment.contains("/") == false && segment.contains("\\") == false); file = new File(file, segment); } return file; } public static File getFile(String rootPath, String... segments) { File file = new File(rootPath); return getFile(file, segments); } public static class FileTraverser { protected Location rootDir; public void traverseDirectory(Location dirLoc) throws IOException { File dir = dirLoc.toFile(); assertTrue(dir.exists() && dir.isDirectory()); rootDir = dirLoc; traverseFileOrDir(dir); } public void traverseFileOrDir(File file) throws IOException { assertTrue(file.exists()); if(file.isDirectory()) { visitDirectory(file); } else { Path relativePath = rootDir == null ? null : rootDir.toPath().relativize(file.toPath()); visitFile(file, relativePath); } } protected void visitDirectory(File dir) throws IOException { File[] children = dir.listFiles(getDefaultDirFilter()); assertTrue(children != null); for (File file : children) { traverseFileOrDir(file); } } protected FilenameFilter getDefaultDirFilter() { return null; } @SuppressWarnings("unused") protected void visitFile(File file, Path relativePath) throws IOException { } } public static void copyDirContentsIntoDirectory(Path sourceDir, Path destFolder) throws IOException { copyDirContentsIntoDirectory(Location.create_fromValid(sourceDir), Location.create_fromValid(destFolder)); } public static void copyDirContentsIntoDirectory(File sourceDir, File destFolder) throws IOException { copyDirContentsIntoDirectory(sourceDir.toPath(), destFolder.toPath()); } public static void copyDirContentsIntoDirectory(Location sourceDir, Location destFolder) throws IOException { assertTrue(sourceDir.toFile().exists()); new FileCopyTraverser(destFolder).traverseDirectory(sourceDir); } public static final class FileCopyTraverser extends FileTraverser { protected final Location destFolder; private FileCopyTraverser(Location destFolder) { this.destFolder = destFolder; } @Override protected void visitFile(File file, Path relativePath) throws IOException { Path targetPath = destFolder.toPath().resolve(relativePath); File targetPathParent = new File(targetPath.toString()).getParentFile(); targetPathParent.mkdirs(); assertTrue(targetPathParent.exists()); Files.copy(file.toPath(), targetPath); } } public static void traverseFiles(File folder, boolean recurseDirs, Function<File, Void> fileVisitor) { traverseFiles(folder, recurseDirs, fileVisitor, null); } public static void traverseFiles(File folder, boolean recurseDirs, Function<File, Void> fileVisitor, FilenameFilter filter) { assertTrue(folder.exists() && folder.isDirectory()); File[] children = folder.listFiles(filter); assertNotNull(children); for (File file : children) { if(file.isDirectory() && recurseDirs) { fileVisitor.apply(file); traverseFiles(file, recurseDirs, fileVisitor, filter); } else { fileVisitor.apply(file); } } } public static void unzipFile(File zipFile, File parentDir, PrintStream logger) throws ZipException, IOException { ZipFile zip = new ZipFile(zipFile); logger.println("== Unzipping: " + zipFile); try { Enumeration<? extends ZipEntry> entries = zip.entries(); while(entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); File entryTargetFile = new File(parentDir, entry.getName()); if(entry.isDirectory()) { entryTargetFile.mkdirs(); continue; } entryTargetFile.getParentFile().mkdirs(); Path destPath = entryTargetFile.toPath(); logger.println("Unzipped: " + entry); logger.println(" to: " + destPath); Files.copy(zip.getInputStream(entry), destPath); } } finally { zip.close(); } } }