com.softicar.platform.common.io.zip.file.ZipFileReader Maven / Gradle / Ivy
Show all versions of platform-common Show documentation
package com.softicar.platform.common.io.zip.file;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Facilitates reading the content of a ZIP archive.
*
* @author Alexander Schmidt
*/
public class ZipFileReader {
private final File zipFile;
/**
* Constructs a new {@link ZipFileReader}.
*
* @param zipFile
* the {@link File} that represents the ZIP archive to read
* (never null)
*/
public ZipFileReader(File zipFile) {
this.zipFile = Objects.requireNonNull(zipFile);
}
/**
* Reads the textual content of the file at the given {@link Path} inside
* the archive.
*
* Returns {@link Optional#empty()} if there is no file at the given
* {@link Path}.
*
* @param filePath
* the path of the file to read, relative to the root of the
* archive (never null)
* @return the textual content
*/
public Optional readTextContent(Path filePath) {
try (var fileSystem = FileSystems.newFileSystem(zipFile.toPath()); var outputStream = new ByteArrayOutputStream()) {
Path path = fileSystem.getPath(filePath.toString());
if (Files.exists(path)) {
Files.copy(path, outputStream);
return Optional.of(outputStream.toString(StandardCharsets.UTF_8));
} else {
return Optional.empty();
}
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
/**
* Finds the {@link Path} of the first file with the given name, inside the
* archive.
*
* The directory tree is traversed in depth-first order.
*
* Returns {@link Optional#empty()} if there is no matching file.
*
* @param filename
* the name of the file to find (never null)
* @return the {@link Path} of the first matching file, relative to the root
* of the archive
*/
public Optional findFirstPath(String filename) {
return findPaths(filename).stream().findFirst();
}
/**
* Finds the {@link Path} of the first file with a name that matches the
* given {@link Pattern}, inside the archive.
*
* The directory tree is traversed in depth-first order.
*
* Returns {@link Optional#empty()} if there is no matching file.
*
* @param filenamePattern
* the {@link Pattern} against which file names shall be matched
* (never null)
* @return the {@link Path} of the first matching file, relative to the root
* of the archive
*/
public Optional findFirstPath(Pattern filenamePattern) {
return findPaths(filenamePattern).stream().findFirst();
}
/**
* Finds the {@link Path}s of all files with the given name, inside the
* archive.
*
* The directory tree is traversed in depth-first order.
*
* @param filename
* the name of the file to find (never null)
* @return the {@link Path}s of all files with the given name (never
* null)
*/
public List findPaths(String filename) {
return findFilePaths(filename::equals);
}
/**
* Finds the {@link Path}s of all files with a name that matches the given
* {@link Pattern}, inside the archive.
*
* The directory tree is traversed in depth-first order.
*
* @param filenamePattern
* the {@link Pattern} against which file names shall be matched
* (never null)
* @return the {@link Path}s of all files with a name that matches the given
* {@link Pattern} (never null)
*/
public List findPaths(Pattern filenamePattern) {
return findFilePaths(filename -> filenamePattern.matcher(filename).find());
}
private List findFilePaths(Predicate filenamePredicate) {
Objects.requireNonNull(filenamePredicate);
try (var fileSystem = FileSystems.newFileSystem(zipFile.toPath())) {
return Files//
.walk(fileSystem.getPath("."))
.filter(filePath -> filenamePredicate.test(filePath.getFileName().toString()))
.collect(Collectors.toList());
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}