com.crabshue.commons.file.nio.FileSystemUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-nio-file Show documentation
Show all versions of commons-nio-file Show documentation
Library for file system operations (using java.nio.file).
package com.crabshue.commons.file.nio;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.file.nio.exceptions.FileErrorContext;
import com.crabshue.commons.file.nio.exceptions.FileErrorType;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
/**
* Utility class for file system operations.s
*/
@Slf4j
public class FileSystemUtils {
/**
* Return or create a folder.
*
* @param folderPath the folder
* @return the already existing / created folder
*/
public static Path provideFolder(@NonNull final Path folderPath) {
if (Files.notExists(folderPath)) {
try {
Files.createDirectories(folderPath);
logger.info("Folder created [{}]", folderPath);
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_CREATING_FOLDER, e)
.addContextValue(FileErrorContext.FOLDER, folderPath);
}
}
return folderPath;
}
/**
* Return or create a subfolder inside the given parent folder.
*
* @param subfolder the name of the subfolder
* @param parentPath the parent folder
* @return the already existing / created subfolder
*/
public static Path provideSubFolder(@NonNull final Path parentPath,
@NonNull final String subfolder) {
Path ret = parentPath.resolve(subfolder);
return provideFolder(ret);
}
/**
* Copy a source file to a target file.
*
* @param filePath the path to the source file.
* @param outputFilePath the path to the target file.
* @return the path to the target file.
*/
public static Path copyFile(@NonNull final Path filePath,
@NonNull final Path outputFilePath) {
final Path ret;
try {
ret = Files.copy(filePath, outputFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_COPY_FILE, e)
.addContextValue(FileErrorContext.FILE, filePath)
.addContextValue(FileErrorContext.FILE, outputFilePath);
}
return ret;
}
/**
* Copy a file to a target folder.
*
* @param filePath the file
* @param targetFolderPath the target folder
* @return the copied file
*/
public static Path copyFileToFolder(@NonNull final Path filePath,
@NonNull final Path targetFolderPath) {
if (!Files.isDirectory(targetFolderPath)) {
throw new IllegalArgumentException("target is not a directory " + targetFolderPath);
}
if (!Files.isRegularFile(filePath)) {
throw new IllegalArgumentException("Given file is not a file " + filePath);
}
final Path targetPath = targetFolderPath.resolve(filePath.getFileName());
final Path ret;
try {
ret = Files.copy(filePath, targetPath);
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_COPY_FILE, "Cannot copy file", e)
.addContextValue(FileErrorContext.FILE, filePath)
.addContextValue(FileErrorContext.FILE, targetPath);
}
logger.info("Copied file [{}] to [{}}", filePath, ret);
return ret;
}
/**
* Copy a folder to a target folder.
*
* @param sourceFolderPath the source folder
* @param targetFolderPath the target folder
* @return the copied folder
*/
public static Path copyFolder(@NonNull final Path sourceFolderPath,
@NonNull final Path targetFolderPath) {
if (!Files.isDirectory(sourceFolderPath)) {
throw new IllegalArgumentException("at least one of the parameters is not a directory");
}
try {
Files.walkFileTree(sourceFolderPath, new DuplicateFileVisitor(sourceFolderPath, targetFolderPath));
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_COPY_FILE, "Cannot copy folder", e)
.addContextValue(FileErrorContext.FOLDER, sourceFolderPath)
.addContextValue(FileErrorContext.FOLDER, targetFolderPath);
}
logger.info("Copied folder [{}] to [{}}", sourceFolderPath, targetFolderPath);
return targetFolderPath;
}
/**
* Check if the content of a folder is empty (i.e. doesn't contain any folder nor file)
*
* @param folderPath the folder
* @return true if the folder is empty, false otherwise
*/
public static boolean isFolderEmpty(@NonNull final Path folderPath) {
try {
return Files.list(folderPath).count() <= 0;
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_READING_FILE, e)
.addContextValue(FileErrorContext.FOLDER, folderPath);
}
}
/**
* Retrieve or create a file on the file system, given a folder and a filename.
*
* @param folderPath the folder.
* @param filename the filename.
* @return the file.
*/
public static Path retrieveOrCreateFile(@NonNull final Path folderPath,
@NonNull final String filename) {
final Path ret = folderPath.resolve(filename);
return retrieveOrCreateFile(ret);
}
/**
* Retrieve or create a file.
*
* @param filePath the file
* @return the file
*/
public static Path retrieveOrCreateFile(@NonNull final Path filePath) {
if (Files.notExists(filePath)) {
try {
final Path parentPath = filePath.getParent();
if (parentPath != null) {
provideFolder(parentPath);
}
Files.createFile(filePath);
logger.info("Created file [{}]", filePath);
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_WRITING_FILE, e)
.addContextValue(FileErrorContext.FILE, filePath);
}
} else {
logger.info("Retrieved file [{}]", filePath);
}
return filePath;
}
/**
* Check is a {@link Path file} is empty.
*
* @param filePath the path to a file.
* @return {@code true} if the file is empty; {@code false} otherwise.
*/
public static boolean isFileEmpty(@NonNull final Path filePath) {
try {
return Files.size(filePath) == 0;
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_READING_FILE, "Cannot read file", e)
.addContextValue(FileErrorContext.FILE, filePath);
}
}
/**
* Clean a directory (files and sub-folder recursively).
*
* @param folderPath the {@link Path path} to the folder.
*/
public static void cleanDirectory(@NonNull final Path folderPath) {
if (Files.notExists(folderPath)) {
logger.info("Folder [{}] does not exist. No need to clean.", folderPath);
return;
}
try {
final DirectoryStream paths = Files.newDirectoryStream(folderPath);
paths.forEach(path -> {
try {
if (Files.isRegularFile(path)) {
Files.delete(path);
} else {
cleanDirectory(path);
Files.deleteIfExists(path);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
});
} catch (IOException e) {
throw new SystemException(FileErrorType.ERROR_CLEANING_FOLDER, e)
.addContextValue(FileErrorContext.FOLDER, folderPath);
}
}
private static class DuplicateFileVisitor implements FileVisitor {
private final Path sourceFolderPath;
private final Path targetFolderPath;
public DuplicateFileVisitor(final Path sourceFolderPath, final Path targetFolderPath) {
this.sourceFolderPath = sourceFolderPath;
this.targetFolderPath = targetFolderPath;
}
@Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
final Path pathToFolder = sourceFolderPath.relativize(dir);
final Path outputFolderPath = targetFolderPath.resolve(pathToFolder);
provideFolder(outputFolderPath);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
final Path pathToFile = sourceFolderPath.relativize(file);
final Path outputFilePath = targetFolderPath.resolve(pathToFile);
copyFile(file, outputFilePath);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(final Path file, final IOException exc) throws IOException {
return FileVisitResult.TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
}
private FileSystemUtils() {
}
}