/* The MIT License (MIT)
* Copyright (c) 2014 Nicholas Wright
* http://opensource.org/licenses/MIT
*/
package com.github.dozedoff.commonj.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FileUtil {
private static final String[] ILLEGAL_FILENAME_CHARS = { "/", "\\", ":", "?", "\"", "<", ">", "|" };
private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);
/**
* Use {@link FileUtil#workingDir() instead}
*
* @return
*/
// TODO REMOVE after 0.1.1
@Deprecated
public static File WorkingDir() {
return workingDir().toFile();
}
public static Path workingDir() {
return Paths.get(System.getProperty("user.dir"));
}
public static List<String> pathTokenList(String path) {
LinkedList<String> resultList = new LinkedList<String>();
Scanner scanner = new Scanner(path);
scanner.useDelimiter("\\\\");
// to handle network paths
if (path.startsWith("\\\\")) {
int endPos = path.indexOf("\\", 2);
resultList.add(path.substring(0, endPos));
scanner.next();
scanner.next();
}
while (scanner.hasNext()) {
resultList.add(scanner.next());
}
// check if the last entry (filename) has an extension, if so, split them
if (resultList.peekLast() != null && resultList.peekLast().contains(".")) {
String lastEntry = resultList.pollLast();
int dotPosition = lastEntry.lastIndexOf(".");
String filename = lastEntry.substring(0, dotPosition);
String extension = lastEntry.substring(dotPosition);
resultList.add(filename);
resultList.add(extension);
}
scanner.close();
return resultList;
}
/**
* Move a directory, sub-directories and files to the new location. src\a , dst will result in dst\a
*
* @param source
* the path of the source directory
* @param destination
* the path of the destination directory
* @throws IOException
*/
public static void moveDirectory(Path source, Path destination) throws IOException {
Files.walkFileTree(source, new DirectoryMover(source, destination));
}
public static void moveFileWithStructure(Path source, Path dstDirectory) throws IOException {
if (source == null) {
throw new IllegalArgumentException("Source cannot be null");
}
if (dstDirectory == null) {
throw new IllegalArgumentException("Destination directory cannot be null");
}
Path relativeSource = relativizeToRoot(source);
Path destinationPath = dstDirectory.resolve(relativeSource);
Path destinationParent = destinationPath.getParent();
if(destinationParent == null) {
throw new IllegalArgumentException("Destination path does not have a parent");
}
Files.createDirectories(destinationParent);
Files.move(source, destinationPath);
}
static public String convertDirPathToString(Path directory) {
if (directory == null) {
return null;
} else if ((directory.getRoot() != null) && (directory.equals(directory.getRoot()))) {
return directory.toString().toLowerCase();
} else {
return directory.toString().toLowerCase() + "\\";
}
}
/**
* Remove the root component from the path, returning a relative path. If the path is already relative, it will not be changed. C:\temp\
* becomes \temp\
*
* @param path
* path to remove root from
* @return a relative path
*/
static public Path removeDriveLetter(Path path) {
if (path == null) {
return null;
}
if (path.isAbsolute()) {
return relativizeToRoot(path);
} else {
return path;
}
}
private static Path relativizeToRoot(Path path) {
Path root = path.getRoot();
if(root == null) {
throw new IllegalArgumentException("Path does not have a root component");
}
return root.relativize(path);
}
static public String removeDriveLetter(String path) {
if (path == null) {
return null;
}
Path relPath = removeDriveLetter(Paths.get(path));
Path filenamePath = relPath.getFileName();
if(filenamePath == null) {
throw new IllegalArgumentException("Filename was null, path had zero elements.");
}
String filename = filenamePath.toString();
if (filename.contains(".")) {
return relPath.toString();
} else {
return relPath.toString() + "\\";
}
}
static public boolean hasValidWindowsFilename(String filename) {
return hasValidWindowsFilename(Paths.get(filename));
}
static public boolean hasValidWindowsFilename(Path fullpath) {
if (fullpath == null) {
return false;
}
Path fileNameElement = fullpath.getFileName();
if (fileNameElement == null) {
return false;
}
String filename = fileNameElement.toString();
if (filename.isEmpty()) {
return false;
}
for (String illegalChar : ILLEGAL_FILENAME_CHARS) {
if (filename.contains(illegalChar)) {
return false;
}
}
return true;
}
// TODO REMOVE after 0.1.1
@Deprecated
static public boolean hasValidWindowsFilename(File fullpath) {
return hasValidWindowsFilename(fullpath.toPath());
}
static public String sanitizeFilenameForWindows(String filename) {
String sanitized = filename;
for (String ic : ILLEGAL_FILENAME_CHARS) {
sanitized = sanitized.replace(ic, "_");
}
return sanitized;
}
static class DirectoryMover extends SimpleFileVisitor<Path> {
Path currMoveDir, dstDir, srcDir;
public DirectoryMover(Path srcDir, Path dstDir) {
this.dstDir = dstDir;
this.srcDir = srcDir.getParent();
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
File f = new File(dstDir.toFile(), srcDir.relativize(dir).toString());
// create new directory with identical name in the destination directory
if(f.mkdirs() == false){
logger.error("Failed to create directory {}", f);
}
currMoveDir = f.toPath();
return super.preVisitDirectory(dir, attrs);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.move(file, currMoveDir.resolve(file.getFileName())); // move files
return super.visitFile(file, attrs);
}
@Override
public FileVisitResult postVisitDirectory(Path arg0, IOException arg1) throws IOException {
Files.delete(arg0); // delete the source directory when done
return super.postVisitDirectory(arg0, arg1);
}
}
}