
io.ultreia.java4all.util.Zips Maven / Gradle / Ivy
Show all versions of java-util Show documentation
package io.ultreia.java4all.util;
/*-
* #%L
* Java Util extends by Ultreia.io
* %%
* Copyright (C) 2018 Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* Created by tchemit on 30/12/2017.
*
* @author Tony Chemit - [email protected]
*/
public class Zips {
/**
* Taille du buffer pour les lectures/écritures.
*/
private static final int BUFFER_SIZE = 8 * 1024;
/**
* Uncompress zipped stream in targetDir.
*
* @param stream the zip source stream, stream is closed before return
* @param targetDir the destination directory
* @throws IOException if any problem while unzip
* @since 2.6.6
*/
public static void uncompress(InputStream stream, File targetDir) throws IOException {
uncompressAndRename(stream, targetDir, null, null);
}
/**
* Uncompress zipped stream in targetDir, and rename uncompressed file if
* necessary. If renameFrom or renameTo is null no renaming is done
*
* file in zip use / to separate directory and not begin with /
* each directory ended with /
*
* @param stream the zip source stream, stream is closed before return
* @param targetDir the destination directory
* @param renameFrom pattern to permit rename file before uncompress it
* @param renameTo new name for file if renameFrom is applicable to it
* you can use $1, $2, ... if you have '(' ')' in renameFrom
* @throws IOException if any problem while uncompressing
* @since 2.6.6
*/
public static void uncompressAndRename(InputStream stream,
File targetDir,
String renameFrom,
String renameTo) throws IOException {
try (ZipInputStream in = new ZipInputStream(new BufferedInputStream(stream))) {
ZipEntry entry;
while ((entry = in.getNextEntry()) != null) {
String name = entry.getName();
if (renameFrom != null && renameTo != null) {
name = name.replaceAll(renameFrom, renameTo);
}
File target = new File(targetDir, name);
if (entry.isDirectory()) {
createDirectoryIfNecessary(target);
} else {
createDirectoryIfNecessary(target.getParentFile());
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(target))) {
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
out.write(buffer, 0, len);
}
}
}
}
}
}
/**
* Unzip compressed archive and keep non excluded patterns.
*
* @param file archive file
* @param targetDir destination file
* @param excludes excludes pattern (pattern must match complete entry name including root folder)
* @throws IOException FIXME
*/
public static void uncompressFiltred(File file, File targetDir, String... excludes) throws IOException {
ZipFile zipFile = new ZipFile(file);
Enumeration extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
// add continue to break loop
boolean excludeEntry = false;
if (excludes != null) {
for (String exclude : excludes) {
if (name.matches(exclude)) {
excludeEntry = true;
}
}
}
if (!excludeEntry) {
File target = new File(targetDir, name);
if (entry.isDirectory()) {
createDirectoryIfNecessary(target);
} else {
// get inputstream only here
createDirectoryIfNecessary(target.getParentFile());
try (InputStream in = zipFile.getInputStream(entry)) {
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(target))) {
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = in.read(buffer, 0, 8 * 1024)) != -1) {
out.write(buffer, 0, len);
}
}
}
}
}
}
}
public static void createDirectoryIfNecessary(File dir) {
if (!dir.exists()) {
// do not throw exception if directory was created by another thread
dir.mkdirs();
}
}
/**
* Tests if the given file is a zip file.
*
* @param file the file to test
* @return {@code true} if the file is a valid zip file,
* {@code false} otherwise.
* @since 2.4.9
*/
public static boolean isZipFile(File file) {
boolean result = false;
try {
ZipFile zipFile = new ZipFile(file);
zipFile.close();
result = true;
} catch (IOException e) {
// silent test
}
return result;
}
/**
* Compress 'includes' files in zipFile. If file in includes is directory
* only the directory is put in zipFile, not the file contained in directory
*
* @param zipFile the destination zip file
* @param root for all file in includes that is in this directory, then we
* remove this directory in zip entry name (aka -C for tar), can be null;
* @param includes the files to include in zip
* @throws IOException if any problem while compressing
*/
public static void compressFiles(File zipFile, File root, Collection includes) throws IOException {
try (OutputStream oStream = new FileOutputStream(zipFile)) {
try (ZipOutputStream zipOStream = new ZipOutputStream(oStream)) {
for (File file : includes) {
String entryName = toZipEntryName(root, file);
ZipEntry entry = new ZipEntry(entryName);
entry.setTime(file.lastModified());
zipOStream.putNextEntry(entry);
if (file.isFile() && file.canRead()) {
byte[] readBuffer = new byte[BUFFER_SIZE];
int bytesIn;
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE)) {
while ((bytesIn = bis.read(readBuffer, 0, BUFFER_SIZE)) != -1) {
zipOStream.write(readBuffer, 0, bytesIn);
}
}
}
zipOStream.closeEntry();
}
}
}
}
/**
* supprime le root du fichier
* Converti les '\' en '/' car les zip entry utilise des '/'
* ajoute un '/' a la fin pour les repertoires
* supprime le premier '/' si la chaine commence par un '/'
*
* @param root the root directory
* @param file the file to treate
* @return the zip entry name corresponding to the given {@code file}
* from {@code root} dir.
*/
private static String toZipEntryName(File root, File file) {
String result = file.getPath();
if (root != null) {
String rootPath = root.getPath();
if (result.startsWith(rootPath)) {
result = result.substring(rootPath.length());
}
}
result = result.replace('\\', '/');
if (file.isDirectory()) {
result += '/';
}
while (result.startsWith("/")) {
result = result.substring(1);
}
return result;
}
}