All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.crabshue.commons.file.nio.FileSystemUtils Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
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() {
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy