compression - read - ¿Qué es una buena biblioteca de Java para comprimir/descomprimir archivos?
zip4j (9)
Miré la biblioteca Zip predeterminada que viene con el JDK y las bibliotecas de compresión de Apache y no estoy contento con ellos por 3 razones:
Están hinchados y tienen mal diseño API. ¿Tengo que escribir 50 líneas de salida de matriz de bytes de la placa de caldera, entrada zip, archivar flujos y cerrar flujos relevantes y capturar excepciones y mover buffers de bytes por mi cuenta ? ¿Por qué no puedo tener una API simple como esta
Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null)
yZipper.zip(File targetDirectory, String password = null)
que simplemente funciona?Parece que el proceso de descompresión de archivos comprimidos destruye los metadatos de archivos y el manejo de contraseñas no funciona.
Además, todas las bibliotecas que probé eran 2-3x lentas en comparación con las herramientas zip de la línea de comandos que obtengo con UNIX.
Para mí (2) y (3) son puntos menores, pero realmente quiero una biblioteca bien probada con una interfaz de una línea.
Implementación completa para zip4j / zip4j una carpeta / archivo con zip4j
Descargue el jar desde here y agréguelo a la ruta de compilación de su proyecto. La class
abajo puede comprimir y extraer cualquier archivo o carpeta, con o sin protección de contraseña.
import java.io.File;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import net.lingala.zip4j.core.ZipFile;
public class Compressor {
public static void zip(String targetPath, String destinationFilePath, String password) {
try {
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
if(password.length()>0){
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
parameters.setPassword(password);
}
ZipFile zipFile = new ZipFile(destinationFilePath);
File targetFile = new File(targetPath);
if(targetFile.isFile()){
zipFile.addFile(targetFile, parameters);
}else if(targetFile.isDirectory()){
zipFile.addFolder(targetFile, parameters);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void unzip(String targetZipFilePath, String destinationFolderPath, String password) {
try {
ZipFile zipFile = new ZipFile(targetZipFilePath);
if (zipFile.isEncrypted()) {
zipFile.setPassword(password);
}
zipFile.extractAll(destinationFolderPath);
} catch (Exception e) {
e.printStackTrace();
}
}
/**/ /// for test only
public static void main(String[] args) {
String targetPath = "target//file//or//folder//path";
String zipFilePath = "zip//file//Path";
String unzippedFolderPath = "destination//folder//path";
String password = "your_password"; // keep it EMPTY<""> for applying no password protection
Compressor.zip(targetPath, zipFilePath, password);
Compressor.unzip(zipFilePath, unzippedFolderPath, password);
}/**/
}
¿Echó un vistazo a http://commons.apache.org/vfs/ ? Pretende simplificar muchas cosas para ti. Pero nunca lo he usado en un proyecto.
Tampoco estoy al tanto de las bibliotecas de compresión Java-Native que no sean JDK o Apache Compression.
Recuerdo que una vez que eliminamos algunas características de Apache Ant, tienen muchas utilidades para la compresión / descompresión incorporadas.
El código de ejemplo con VFS se vería así:
File zipFile = ...;
File outputDir = ...;
FileSystemManager fsm = VFS.getManager();
URI zip = zipFile.toURI();
FileObject packFileObject = fsm.resolveFile(packLocation.toString());
FileObject to = fsm.toFileObject(destDir);
FileObject zipFS;
try {
zipFS = fsm.createFileSystem(packFileObject);
fsm.toFileObject(outputDir).copyFrom(zipFS, new AllFileSelector());
} finally {
zipFS.close();
}
Aquí hay un ejemplo completo para comprimir y descomprimir archivos recursivamente: http://developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using-Apache-Commons-Compress
Con IOUtils
Apache Commons-IO puedes hacer esto:
java.util.zip.ZipFile zipFile = new ZipFile(file);
try {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File entryDestination = new File(outputDir, entry.getName());
if (entry.isDirectory()) {
entryDestination.mkdirs();
} else {
entryDestination.getParentFile().mkdirs();
InputStream in = zipFile.getInputStream(entry);
OutputStream out = new FileOutputStream(entryDestination);
IOUtils.copy(in, out);
IOUtils.closeQuietly(in);
out.close();
}
}
} finally {
zipFile.close();
}
Todavía es un código repetitivo, pero solo tiene una dependencia no exótica: Commons-IO
Extraiga el archivo zip y todas sus subcarpetas, utilizando solo el JDK:
private void extractFolder(String zipFile,String extractFolder)
{
try
{
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile zip = new ZipFile(file);
String newPath = extractFolder;
new File(newPath).mkdir();
Enumeration zipFileEntries = zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements())
{
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
//destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory())
{
BufferedInputStream is = new BufferedInputStream(zip
.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
}
}
catch (Exception e)
{
Log("ERROR: "+e.getMessage());
}
}
Archivos zip y todas sus subcarpetas:
private void addFolderToZip(File folder, ZipOutputStream zip, String baseName) throws IOException {
File[] files = folder.listFiles();
for (File file : files) {
if (file.isDirectory()) {
addFolderToZip(file, zip, baseName);
} else {
String name = file.getAbsolutePath().substring(baseName.length());
ZipEntry zipEntry = new ZipEntry(name);
zip.putNextEntry(zipEntry);
IOUtils.copy(new FileInputStream(file), zip);
zip.closeEntry();
}
}
}
Otra opción es JZlib . En mi experiencia, es menos "centrado en el archivo" que zip4J, por lo que si necesita trabajar en blobs en memoria en lugar de archivos, puede echarle un vistazo.
Otra opción que puede consultar es zt-zip disponible desde la página central y del proyecto de Maven en https://github.com/zeroturnaround/zt-zip
Tiene la funcionalidad de empaquetado y desempaque estándar (en secuencias y en el sistema de archivos) + muchos métodos de ayuda para probar los archivos en un archivo o agregar / eliminar entradas.
Sé que es tarde y hay muchas respuestas, pero este zip4j es una de las mejores bibliotecas para comprimir que he usado. Es simple (sin código de caldera) y puede manejar fácilmente archivos protegidos por contraseña.
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.core.ZipFile;
public static void unzip(){
String source = "some/compressed/file.zip";
String destination = "some/destination/folder";
String password = "password";
try {
ZipFile zipFile = new ZipFile(source);
if (zipFile.isEncrypted()) {
zipFile.setPassword(password);
}
zipFile.extractAll(destination);
} catch (ZipException e) {
e.printStackTrace();
}
}
La dependencia de Maven es:
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
Un proyecto muy bonito es TrueZip .
TrueZIP es un marco de plug-in basado en Java para sistemas de archivos virtuales (VFS) que proporciona acceso transparente a archivos comprimidos como si fueran directorios simples
Por ejemplo (desde el website ):
File file = new TFile("archive.tar.gz/README.TXT");
OutputStream out = new TFileOutputStream(file);
try {
// Write archive entry contents here.
...
} finally {
out.close();
}