
org.cp.elements.io.FileUtils Maven / Gradle / Ivy
/*
* Copyright 2011-Present Author or Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cp.elements.io;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.List;
import java.util.stream.Collectors;
import org.cp.elements.lang.Assert;
import org.cp.elements.lang.ObjectUtils;
import org.cp.elements.lang.StringUtils;
import org.cp.elements.lang.annotation.NotNull;
import org.cp.elements.lang.annotation.NullSafe;
import org.cp.elements.lang.annotation.Nullable;
import org.cp.elements.util.ArrayUtils;
/**
* Abstract utility class encapsulating methods used to process {@link File Files}.
*
* @author John J. Blum
* @see java.io.File
* @see java.io.FileOutputStream
* @see java.io.FileReader
* @see java.io.InputStream
* @see java.io.OutputStream
* @see org.cp.elements.io.IOUtils
* @since 1.0.0
*/
@SuppressWarnings("unused")
public abstract class FileUtils extends IOUtils {
public static final String CLASS_FILE_EXTENSION = ".class";
public static final String GROOVY_FILE_EXTENSION = ".groovy";
public static final String JAVA_FILE_EXTENSION = ".java";
public static final String KOTLIN_FILE_EXTENSION = ".kt";
protected static final boolean DEFAULT_FILE_FILTER_ACCEPT_RETURN_VALUE = true;
protected static final boolean DEFAULT_FILENAME_FILTER_ACCEPT_RETURN_VALUE = true;
protected static final String FILE_EXTENSION_SEPARATOR = StringUtils.DOT_SEPARATOR;
protected static final String NO_FILE_EXTENSION = StringUtils.EMPTY_STRING;
protected static final String NO_FILE_NAME = StringUtils.EMPTY_STRING;
/**
* Asserts that the given {@link File} exists.
*
* @param path {@link File} to assert for existence.
* @return the given {@link File}; never {@literal null}.
* @throws java.io.FileNotFoundException if the {@link File} does not exist.
* @see #isExisting(File)
* @see java.io.File
*/
@NullSafe
public static @NotNull File assertExists(@Nullable File path) throws FileNotFoundException {
if (isExisting(path)) {
return path;
}
throw new FileNotFoundException(String.format("[%s] was not found", path));
}
/**
* Creates a file system directory with the given {@link File path}.
*
* @param path {@link File} referring to the file system path of the directory to create.
* @return {@literal true} if the {@literal path} represented by the {@link File} is not {@literal null},
* is not an existing {@link File#isFile()}, or the {@literal path} can be created as a directory.
* Returns {@literal true} if the directory already exists.
* @see java.io.File#mkdirs()
*/
@NullSafe
public static boolean createDirectory(@Nullable File path) {
return path != null
&& !path.isFile()
&& (path.isDirectory() || path.mkdirs());
}
/**
* Creates a file system file with the given {@link File path}.
*
* @param path {@link File} referring to the absolute location and name of the file to create.
* @return {@literal true} if the path represented by the {@link File} is not {@literal null},
* is not an existing {@link File#isDirectory()}, or the {@literal path} can be created as a file.
* Returns {@literal true} if the file already exists.
* @see java.io.File#createNewFile()
*/
@NullSafe
public static boolean createFile(@Nullable File path) {
try {
return path != null
&& !path.isDirectory()
&& (path.isFile() || path.createNewFile());
}
catch (IOException ignore) {
return false;
}
}
/**
* Deletes the given {@link File}.
*
* @param path {@link File} to delete.
* @return a boolean value indicating whether the given {@link File} was deleted successfully.
* Returns {@literal false} if the {@link File} references is {@literal null}
* or does not {@link #isExisting(File) exist}.
* @see java.io.File#delete()
* @see #isExisting(File)
*/
@NullSafe
public static boolean delete(@Nullable File path) {
return isExisting(path) && path.delete();
}
/**
* Returns the {@link String extension} of the given, required {@link File}.
*
* @param file {@link File} from which to get the {@link String extension}; must not be {@literal null}.
* @return the {@link File} {@link String extension} or an empty {@link String} if the {@link File}
* does not have an {@link String extension}.
* @throws IllegalArgumentException if the {@link File} reference is {@literal null}.
* @see java.io.File#getName()
*/
public static @NotNull String getExtension(@NotNull File file) {
Assert.notNull(file, "File is required");
String filename = file.getName();
int dotIndex = filename.indexOf(FILE_EXTENSION_SEPARATOR);
return dotIndex > -1 ? filename.substring(dotIndex + 1) : NO_FILE_EXTENSION;
}
/**
* Returns the {@link String absolute path (location)} of the given, required {@link File}.
*
* @param file {@link File} to determine {@link String absolute filesystem path}; must not be {@literal null}.
* @return a {@link String} containing the {@literal absolute filesystem pathname (location)}
* of the given {@link File}.
* @throws IllegalArgumentException if the {@link File} reference is {@literal null}.
* @see #tryGetCanonicalPathElseGetAbsolutePath(java.io.File)
* @see java.io.File#getParentFile()
*/
public static @NotNull String getLocation(@NotNull File file) {
Assert.notNull(file, "File is required");
File parent = file.getParentFile();
Assert.notNull(parent, "Location of file [%s] cannot be determined", file);
return tryGetCanonicalPathElseGetAbsolutePath(parent);
}
/**
* Returns the {@link String name} of the given, required {@link File}
* without the {@link File File's} {@link String extension}.
*
* @param file {@link File} to get the {@link String name} of; must not be {@literal null}.
* @return a {@link String} containing the {@literal name} of the {@link File}.
* @throws IllegalArgumentException if the {@link File} reference is {@literal null}.
* @see java.io.File#getName()
*/
public static @NotNull String getName(@NotNull File file) {
Assert.notNull(file, "File is required");
String filename = file.getName();
int dotIndex = filename.indexOf(FILE_EXTENSION_SEPARATOR);
int fileSeparatorIndex = filename.lastIndexOf(File.separator);
filename = dotIndex != -1 ? filename.substring(0, dotIndex) : filename;
filename = fileSeparatorIndex != -1 ? filename.substring(fileSeparatorIndex) : filename;
return filename.trim();
}
/**
* Determines whether the given {@link File} exists and is a {@link File#isDirectory() directory}.
*
* @param path {@link File} to evaluate as a directory.
* @return a boolean value indicating whether the given {@link File} is a {@link File#isDirectory() directory}.
* @see java.io.File#isDirectory()
*/
@NullSafe
public static boolean isDirectory(@Nullable File path) {
return path != null && path.isDirectory();
}
/**
* Determines whether the given {@link File} has any content.
*
* If the {@link File} refers to a {@link File#isDirectory() directory}, then the directory is empty
* if it contains not files or subdirectories.
*
* @param path {@link File} to evaluate for content.
* @return a boolean value indicating whether the given {@link File} has any content.
* @see java.io.File#length()
* @see #isDirectory(File)
* @see #size(File)
*/
@NullSafe
public static boolean isEmpty(@Nullable File path) {
return isDirectory(path)
? ArrayUtils.nullSafeLength(path.listFiles()) == 0
: size(path) == 0L;
}
/**
* Determines whether the given {@link File} has any content.
*
* @param path {@link File} to evaluate for content.
* @return a boolean value indicating whether the given {@link File} has any content.
* @see #isEmpty(File)
* @see java.io.File
*/
@NullSafe
public static boolean isNotEmpty(@Nullable File path) {
return !isEmpty(path);
}
/**
* Determines whether the given {@link File} {@link File#exists()}.
*
* @param path {@link File} to evaluate.
* @return a boolean valued indicating whether the given {@link File} {@link File#exists()}.
* @see java.io.File#exists()
*/
@NullSafe
public static boolean isExisting(@Nullable File path) {
return path != null && path.exists();
}
/**
* Determines whether the given {@link File} {@link File#exists()}.
*
* @param path {@link File} to evaluate.
* @return a boolean valued indicating whether the given {@link File} {@link File#exists()}.
* @see #isExisting(File)
* @see java.io.File
*/
public static boolean isNonExisting(@Nullable File path) {
return !isExisting(path);
}
/**
* Determines whether the given {@link File} exists and is a {@link File#isFile() file}.
*
* @param path {@link File} to evaluate as a file.
* @return a boolean valued indicating whether the given {@link File} exists and is a {@link File#isFile() file}.
* @see java.io.File#isFile()
*/
@NullSafe
public static boolean isFile(@Nullable File path) {
return path != null && path.isFile();
}
/**
* Constructs a new instance of {@link File} initialized with the given {@link String pathname}.
*
* @param pathname {@link String} containing the {@literal pathname} of the {@link File} to create;
* must not be {@literal null}.
* @return a new {@link File} with the given {@link String pathname}.
* @throws IllegalArgumentException if the {@link String pathname} is {@literal null}.
* @see java.io.File#File(String)
*/
public static @NotNull File newFile(@NotNull String pathname) {
return new File(ObjectUtils.requireObject(pathname, "A pathname for the File is required"));
}
/**
* Utility method used to guard against a potentially {@literal null} {@link FileFilter}.
*
* By default, the {@link FileFilter} returned when the given {@link FileFilter} is {@literal null}
* {@link FileFilter#accept(File) accepts} all {@link File files}.
*
* @param fileFilter {@link FileFilter} to evaluate.
* @return the given {@link FileFilter} if not {@literal null}, otherwise returns a {@link FileFilter}
* {@link FileFilter#accept(File) accepting} all {@link File files}.
* @see #nullSafeFileFilter(FileFilter, boolean)
* @see java.io.FileFilter
*/
public static @NotNull FileFilter nullSafeFileFilter(@Nullable FileFilter fileFilter) {
return nullSafeFileFilter(fileFilter, DEFAULT_FILE_FILTER_ACCEPT_RETURN_VALUE);
}
/**
* Utility method used to guard against a potentially {@literal null} {@link FileFilter}.
*
* @param fileFilter {@link FileFilter} to evaluate.
* @param accept boolean value returned by the generated {@link FileFilter} when the given {@link FileFilter}
* is {@literal null}.
* @return the given {@link FileFilter} if not {@literal null}, otherwise returns a generated {@link FileFilter}.
* @see java.io.FileFilter
*/
public static @NotNull FileFilter nullSafeFileFilter(@Nullable FileFilter fileFilter, boolean accept) {
return fileFilter != null ? fileFilter : file -> accept;
}
/**
* Utility method used to guard against a potentially {@literal null} {@link FilenameFilter}.
*
* By default, the {@link FilenameFilter} returned when the given {@link FilenameFilter} is {@literal null}
* {@link FilenameFilter#accept(File, String) accepts} all {@link File files}.
*
* @param filenameFilter {@link FilenameFilter} to evaluate.
* @return the given {@link FilenameFilter} if not {@literal null}, otherwise returns a {@link FilenameFilter}
* {@link FilenameFilter#accept(File, String) accepting} all {@link File files}.
* @see #nullSafeFilenameFilter(FilenameFilter, boolean)
* @see java.io.FilenameFilter
*/
public static @NotNull FilenameFilter nullSafeFilenameFilter(@Nullable FilenameFilter filenameFilter) {
return nullSafeFilenameFilter(filenameFilter, DEFAULT_FILENAME_FILTER_ACCEPT_RETURN_VALUE);
}
/**
* Utility method used to guard against a potentially {@literal null} {@link FilenameFilter}.
*
* @param filenameFilter {@link FilenameFilter} to evaluate.
* @param accept boolean value returned by the generated {@link FilenameFilter}
* when the given {@link FilenameFilter} is {@literal null}.
* @return the given {@link FilenameFilter} if not {@literal null},
* otherwise returns a generated {@link FilenameFilter}.
* @see java.io.FilenameFilter
*/
public static @NotNull FilenameFilter nullSafeFilenameFilter(@Nullable FilenameFilter filenameFilter,
boolean accept) {
return filenameFilter != null ? filenameFilter : (file, filename) -> accept;
}
/**
* Reads the contents of the given, required {@link File} into a {@link String}.
*
* @param file {@link File} to read; must not be {@literal null}.
* @return a {@link String} containing the contents of the {@link File}.
* @throws IllegalArgumentException if the {@link File} is not a valid file.
* @throws IllegalStateException if the {@link File} is not readable.
* @throws IOException if the given {@link File} cannot be read.
* @see #readLines(File)
* @see java.io.File
*/
public static @NotNull String read(@NotNull File file) throws IOException {
StringBuilder buffer = new StringBuilder();
readLines(file).forEach(line -> {
buffer.append(line);
buffer.append(StringUtils.LINE_SEPARATOR);
});
return buffer.toString().trim();
}
/**
* Reads the contents of the given, required {@link File} into a {@link List} containing an {@link String element}
* for each {@link String line} in the {@link File}.
*
* @param file {@link File} to read the contents from; must not be {@literal null}.
* @return a {@link List} of {@link String Strings} containing the contents of the {@link File}.
* @throws IOException if an I/O error occurs while reading the {@link File}.
* @throws IllegalArgumentException if the {@link File} is not a valid file.
* @throws IllegalStateException if the {@link File} cannot be read.
* @see java.io.File#canRead()
* @see #isFile(File)
*/
public static List readLines(@NotNull File file) throws IOException {
Assert.isTrue(isFile(file), "[%s] must be a file", file);
Assert.state(file.canRead(), "[%s] is not readable", tryGetCanonicalPathElseGetAbsolutePath(file));
try (BufferedReader fileReader = new BufferedReader(new FileReader(file))) {
return fileReader.lines().collect(Collectors.toList());
}
}
/**
* Determines the size in bytes of the given {@link File}.
*
* If the {@link File} is {@literal null} or does not {@link File#exists() exist}, then {@literal 0} is returned.
*
* @param path {@link File} to evaluate.
* @return a {@link Long#TYPE} value for the size of the {@link File} in bytes. If the {@link File} is {@literal null}
* or does not {@link File#exists() exist}, then {@literal 0} is returned.
* @see java.io.File#length()
* @see #isFile(File)
*/
@NullSafe
public static long size(@Nullable File path) {
return isFile(path) ? path.length() : 0L;
}
/**
* Converts the given, required {@link File File's} {@link File#lastModified() last modified timestamp}
* to a {@link LocalDateTime}.
*
* @param file {@link File} to process; must not be {@literal null}.
* @return a {@link LocalDateTime} for the {@link File File's} {@link File#lastModified() last modified timestamp}.
* @throws IllegalArgumentException if the {@link File} is {@literal null}.
* @see java.time.LocalDateTime
* @see java.io.File
*/
public static @NotNull LocalDateTime toLastModifiedDateTime(@NotNull File file) {
Assert.notNull(file, "File is required");
return Instant.ofEpochMilli(file.lastModified())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}
/**
* Converts the given, required {@link File File's} {@link File#lastModified() last modified timestamp}
* to a {@link LocalDate}, stripping off the {@link LocalTime time} component.
*
* @param file {@link File} to process; must not be {@literal null}.
* @return the {@link LocalDate} from the {@link File File's} {@link File#lastModified() last modified timestamp}
* stripping off the {@link LocalTime time} component.
* @throws IllegalArgumentException if the {@link File} is {@literal null}.
* @see #toLastModifiedDateTime(File)
* @see java.time.LocalDate
* @see java.io.File
*/
public static @NotNull LocalDate toLastModifiedDate(@NotNull File file) {
return toLastModifiedDateTime(file).toLocalDate();
}
/**
* Converts the given, required {@link File File's} {@link File#lastModified() last modified timestamp}
* to a {@link LocalTime}, stripping off the {@link LocalDate date} component.
*
* @param file {@link File} to process; must not be {@literal null}.
* @return the {@link LocalTime} from the {@link File File's} {@link File#lastModified() last modified timestamp}
* stripping off the {@link LocalTime date} component.
* @throws IllegalArgumentException if the {@link File} is {@literal null}.
* @see #toLastModifiedDateTime(File)
* @see java.time.LocalTime
* @see java.io.File
*/
public static @NotNull LocalTime toLastModifiedTime(@NotNull File file) {
return toLastModifiedDateTime(file).toLocalTime();
}
/**
* Attempts to the get the {@link File#getCanonicalFile() canonical form} of the given {@link File},
* otherwise returns the {@link File#getAbsoluteFile() absolute form} of the {@link File}.
*
* @param file {@link File} from which to return the {@link File#getCanonicalFile()}; must not be {@literal null}.
* @return the {@link File#getCanonicalFile() canonical form} of the {@link File} unless an {@link IOException} occurs
* then return the {@link File#getAbsoluteFile() absolute form} of the {@link File}.
* @throws IllegalArgumentException if the {@link File} reference is {@literal null}.
* @see java.io.File#getCanonicalFile()
* @see java.io.File#getAbsoluteFile()
*/
public static @NotNull File tryGetCanonicalFileElseGetAbsoluteFile(@NotNull File file) {
try {
return ObjectUtils.requireObject(file, "File is required").getCanonicalFile();
}
catch (IOException ignore) {
return file.getAbsoluteFile();
}
}
/**
* Attempts to the get the {@link File#getCanonicalPath() canonical form} of the given {@link File},
* otherwise returns the {@link File#getAbsolutePath() absolute form} of the {@link File}.
*
* @param file {@link File} from which to return the {@link File#getCanonicalPath()}; must not be {@literal null}.
* @return the {@link File#getCanonicalPath() canonical form} of the {@link File} unless an {@link IOException} occurs
* then return the {@link File#getAbsolutePath() absolute form} of the {@link File}.
* @throws IllegalArgumentException if the {@link File} reference is {@literal null}.
* @see java.io.File#getCanonicalPath()
* @see java.io.File#getAbsolutePath()
*/
public static @NotNull String tryGetCanonicalPathElseGetAbsolutePath(@NotNull File file) {
try {
return ObjectUtils.requireObject(file, "File is required").getCanonicalPath();
}
catch (IOException ignore) {
return file.getAbsolutePath();
}
}
/**
* Writes the contents of the given, required {@link InputStream} to the given, required {@link File}.
*
* @param in {@link InputStream} used as the source of the {@link File} content; must not be {@literal null}.
* @param file {@link File} to write the contents of the {@link InputStream} to; must not be {@literal null}.
* @return the given {@link File} reference containing the contents of the {@link InputStream}.
* @throws IllegalArgumentException if either the {@link InputStream} or {@link File} reference are {@literal null}.
* @throws IllegalStateException if the {@link File} {@link File#exists()}
* and is not {@link File#canWrite() writable}.
* @throws IOException if an I/O error occurs while writing the contents of the {@link InputStream}
* to the {@link File}.
* @see #copy(InputStream, OutputStream)
* @see java.io.InputStream
* @see java.io.File
*/
public static File write(@NotNull InputStream in, @NotNull File file) throws IOException {
Assert.notNull(in, "InputStream is required");
Assert.notNull(file, "File is required");
boolean isWritable = isNonExisting(file) || file.canWrite();
Assert.state(isWritable, "[%s] is not writable", tryGetCanonicalPathElseGetAbsolutePath(file));
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
copy(in, out);
}
return file;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy