com.github.ormfux.common.utils.FileUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ormfux-common-util Show documentation
Show all versions of ormfux-common-util Show documentation
A small collection of Java utilities for every-day use
package com.github.ormfux.common.utils;
import static com.github.ormfux.common.utils.NullableUtils.nonNull;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
//import org.apache.commons.lang3.StringUtils;
/**
* Utilities for file handling.
*/
public final class FileUtils {
private FileUtils() {
throw new IllegalAccessError(FileUtils.class.getSimpleName() + " class is not intended to be instantiated");
}
/**
* Reads the contents of a file into an UTF-8 encoded String.
*
* @param filePath The path to the file.
* @return The file content as String.
*
* @throws IOException
*/
public static String readFile(final String filePath) throws IOException {
return readStream(new FileInputStream(filePath));
}
/**
* Reads the contents of a stream into an UTF-8 encoded String.
*
* @param inputStream The data stream.
* @return The stream as String.
*
* @throws IOException
*/
public static String readStream(final InputStream inputStream) throws IOException {
//the fasted way to read the file
//https://stackoverflow.com/a/35446009
try {
final ByteArrayOutputStream sqlBytes = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
sqlBytes.write(buffer, 0, length);
}
return sqlBytes.toString("UTF-8");
} finally {
try {
inputStream.close();
} catch (final IOException e) {
//close silently.
}
}
}
/**
* Gets the names of all files in the directory, which is part of the class path. Can read from a directory
* available as "loose file" or from a directory contained in a {@code *.jar} archive of the application.
*
* @param directory The fully qualified directory path.
* @param classPathIndicator The class, which provides the "jar" or "loose file" information. The directory is looked
* up in the jar containing this class.
* @return The (local!) names of the files and directories contained in the given directory
* @throws IOException
*/
//TODO add module support
public static List readClassPathDirectoryContent(final String directory, final Class> classPathIndicator) throws IOException {
if (!directory.startsWith("/")) {
throw new IllegalArgumentException("The directory name must be a full path (i.e. start with '/').");
}
final URL indicatorUrl = classPathIndicator.getClassLoader().getResource(classPathIndicator.getName().replaceAll("\\.", "/") + ".class");
final List directoryContent;
if ("file".equals(indicatorUrl.getProtocol())) {
directoryContent = readFilesFromLooseDirectory(directory, classPathIndicator);
} else if ("jar".equals(indicatorUrl.getProtocol())) {
directoryContent = readFilesFromJarDirectory(directory, indicatorUrl);
} else {
throw new IOException("Cannot read directory: " + indicatorUrl);
}
Collections.sort(directoryContent);
return directoryContent;
}
/**
* Reads the file and directory names of a directory, which is a loose directory on the class path.
*
* @param directory The fully qualified directory name in the jar file.
* @param directoryUrl The URL to the loose directory.
* @return The names of the files and directories in the jar's nested directory.
*
* @throws IOException
* @throws UnsupportedEncodingException
*/
private static List readFilesFromLooseDirectory(final String directory, final Class> classPathIndicator) throws IOException {
final URL directoryUrl = classPathIndicator.getClassLoader().getResource(directory.substring(1));
if (nonNull(directoryUrl)) {
final File directoryFile = new File(directoryUrl.getFile());
if (directoryFile.isDirectory()) {
return ListUtils.fromArray(directoryFile.list());
} else {
throw new FileNotFoundException("This is not a directory: " + directory);
}
} else {
return new ArrayList<>();
}
}
/**
* Reads the file and directory names of a directory, which is stored in a jar-archive.
*
* @param directory The fully qualified directory name in the jar file.
* @param directoryUrl The URL to the jar file. Path must be "{@code file:...}"
* @return The names of the files and directories in the jar's nested directory.
*
* @throws IOException
* @throws UnsupportedEncodingException
*/
private static List readFilesFromJarDirectory(final String directory,
final URL directoryUrl) throws IOException, UnsupportedEncodingException {
final List directoryContent = new ArrayList<>();
final String jarPath = directoryUrl.getPath().substring("file:".length(), directoryUrl.getPath().indexOf('!'));
final JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
final Enumeration jarEntries = jar.entries();
while (jarEntries.hasMoreElements()) {
final JarEntry jarEntry = jarEntries.nextElement();
final String entryName;
if (!jarEntry.getName().startsWith("/")) {
entryName = '/' + jarEntry.getName();
} else {
entryName = jarEntry.getName();
}
if (entryName.startsWith(directory) && entryName.length() > (directory.length() + 1)) {
final String subPath = entryName.substring(directory.length() + 1);
final String localEntryName;
if (subPath.indexOf('/') >= 0) {
//sub-directory >> add only the sub-directory name
localEntryName = subPath.substring(0, subPath.indexOf('/'));
} else {
localEntryName = subPath;
}
if (!directoryContent.contains(localEntryName)) {
directoryContent.add(localEntryName);
}
}
}
jar.close();
return directoryContent;
}
}