Crear archivo zip en Java

Tengo un archivo creado por el progtwig 7zip. Usé el método de desinflar para comprimirlo. Ahora quiero crear el mismo archivo (con el mismo MD5sum) en java . Cuando creo el archivo zip, utilicé el algoritmo que encontré en Internet, por ejemplo http://www.kodejava.org/examples/119.html pero cuando creé el archivo zip con este método, el tamaño comprimido es más alto que el tamaño de el archivo descomprimido, entonces, ¿qué está pasando? Esta no es una compresión muy útil. Entonces, ¿cómo puedo crear un archivo zip que sea exactamente igual al archivo zip que creé con el progtwig 7zip? Si me sirve, tengo toda la información sobre el archivo zip que creé en el progtwig 7zip.

 // simplified code for zip creation in java import java.io.*; import java.util.zip.*; public class ZipCreateExample { public static void main(String[] args) throws Exception { // input file FileInputStream in = new FileInputStream("F:/sometxt.txt"); // out put file ZipOutputStream out = new ZipOutputStream(new FileOutputStream("F:/tmp.zip")); // name the file inside the zip file out.putNextEntry(new ZipEntry("zippedjava.txt")); // buffer size byte[] b = new byte[1024]; int count; while ((count = in.read(b)) > 0) { out.write(b, 0, count); } out.close(); in.close(); } } 

Solo para aclarar, ¿usaste el algoritmo ZIP en 7zip para tu original? Además, 7zip afirma tener una relación de compresión de 2-10% mejor que otros proveedores. Me arriesgaría a suponer que el algoritmo ZIP incorporado en Java no está tan optimizado como el de 7zip. Lo mejor que puede hacer es invocar 7zip desde la línea de comandos si quiere un archivo similarmente comprimido.

¿Estás tratando de descomprimir un archivo ZIP, cambiar un archivo dentro de él y luego volver a comprimirlo para que tenga el mismo hash MD5? Los hashes están destinados a evitar que hagas eso.

ZipOutputStream tiene algunos métodos para ajustar la compresión:

public void setMethod (método int)

Establece el método de compresión predeterminado para las siguientes entradas. Este valor predeterminado se usará siempre que el método de compresión no se especifique para una entrada de archivo ZIP individual, y se establece inicialmente en DEFLATED.

public void setLevel (nivel int)

Establece el nivel de compresión para las entradas subsiguientes que están DESINFLADAS. La configuración predeterminada es DEFAULT_COMPRESSION. nivel – el nivel de compresión (0-9)

Cuando agregas algo como:

 ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(target)); zos.setMethod( ZipOutputStream.DEFLATED ); zos.setLevel( 5 ); ... 

¿no mejora su compresión?

Aquí hay una función que pasa la ruta absoluta creará un archivo zip con el mismo nombre que el directorio (debajo del cual desea el zip de todos los subcarpetas y archivos, ¡todo!) Y devolverá true al éxito y falso a la excepción Si alguna.

 public class FileUtil { final static int BUFFER = 2048; private static Logger log = Logger.getLogger(FileUtil.class); public static boolean createZipArchive(String srcFolder) { try { BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream(new File(srcFolder+ ".zip")); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest)); byte data[] = new byte[BUFFER]; File subDir = new File(srcFolder); String subdirList[] = subDir.list(); for(String sd:subdirList) { // get a list of files from current directory File f = new File(srcFolder+"/"+sd); if(f.isDirectory()) { String files[] = f.list(); for (int i = 0; i < files.length; i++) { System.out.println("Adding: " + files[i]); FileInputStream fi = new FileInputStream(srcFolder + "/"+sd+"/" + files[i]); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(sd +"/"+files[i]); out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); out.flush(); } } } else //it is just a file { FileInputStream fi = new FileInputStream(f); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(sd); out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); out.flush(); } } } origin.close(); out.flush(); out.close(); } catch (Exception e) { log.info("createZipArchive threw exception: " + e.getMessage()); return false; } return true; } } 

Para generar dos archivos zip idénticos (incluido el md5sum idéntico) del mismo archivo fuente, recomendaría usar la misma utilidad zip, ya sea siempre use el mismo progtwig Java o siempre use 7zip.

La utilidad 7zip, por ejemplo, tiene muchas opciones, muchas de las cuales son simplemente valores predeterminados que pueden personalizarse (o diferir entre lanzamientos), y cualquier implementación de Java zip debería establecer también estas opciones de forma explícita. Si su aplicación Java simplemente puede invocar un progtwig externo “7z”, probablemente obtenga un mejor rendimiento de todos modos que una implementación de Java zip personalizada. (Este también es un buen ejemplo de un problema de reducción de mapas donde puede escalar fácilmente la implementación).

Pero el problema principal con el que se encontrará si tiene un archivo zip generado en el servidor y un archivo zip generado en el lado del cliente es que el archivo zip almacena dos cosas además del archivo original: (1) el nombre del archivo y (2) la marca de tiempo del archivo. Si alguno de estos ha cambiado, entonces el archivo zip resultante tendrá un md5sum diferente:

 $ ls tst1/ foo.tar $ cp -r tst1 tst2 $ ( cd tst1; zip foo.zip foo.tar ) ; ( cd tst2; zip foo.zip foo.tar ) ; md5sum tst?/foo.zip updating: foo.tar (deflated 20%) updating: foo.tar (deflated 20%) 359b82678a2e17c1ddbc795ceeae7b60 tst1/foo.zip b55c33c0414ff987597d3ef9ad8d1d08 tst2/foo.zip 

Pero, usando “cp -p” (preserve timestamp):

 $ cp -p -r tst1 tst2 $ ( cd tst1; zip foo.zip foo.tar ) ; ( cd tst2; zip foo.zip foo.tar ) ; md5sum tst?/foo.zip updating: foo.tar (deflated 20%) updating: foo.tar (deflated 20%) 359b82678a2e17c1ddbc795ceeae7b60 tst1/foo.zip 359b82678a2e17c1ddbc795ceeae7b60 tst2/foo.zip 

Encontrará el mismo problema con diferentes nombres de archivos y rutas, incluso cuando los archivos dentro del zip sean idénticos.

 package comm; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream;*emphasized text* import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class Zip1 { public static void main( String[] args ) { byte[] buffer = new byte[1024]; try{ File f= new File("E:\\"); f.mkdirs(); File origFile= new File(f,"MyZipFile2.zip"); FileOutputStream fos = new FileOutputStream(origFile); ZipOutputStream zos = new ZipOutputStream(fos); ZipEntry ze= new ZipEntry("test.pdf"); zos.putNextEntry(ze); FileInputStream in = new FileInputStream("D:\\Test.pdf"); int len; while ((len = in.read(buffer)) > 0) { zos.write(buffer, 0, len); } in.close(); zos.closeEntry(); //remember close it zos.close(); System.out.println("Done"); }catch(IOException ex){ ex.printStackTrace(); } } } 

En el siguiente código encontrará las funcionalidades para comprimir y descomprimir . Espero que pueda ayudar a alguien.

 package com.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * @author dinesh.lomte * */ public class ZipUtil { /** * * @param source * @param destination */ public static void unZip(String source, String destination) { String method = "unZip(String source, String destination)"; ZipInputStream zipInputStream = null; try { // Creating the ZipInputStream instance from the source file zipInputStream = new ZipInputStream(new FileInputStream(source)); // Getting the zipped file list entry ZipEntry zipEntry = zipInputStream.getNextEntry(); // Iterating through the file list entry while (zipEntry != null) { String fileName = zipEntry.getName(); File file = new File(new StringBuilder(destination) .append(File.separator) .append(AppUtil.getFileNameWithoutExtension( AppUtil.getNameFromPath(source))) .append(File.separator).append(fileName).toString()); // Creating non existing folders to avoid any FileNotFoundException // for compressed folder new File(file.getParent()).mkdirs(); FileOutputStream fileOutputStream = new FileOutputStream(file); byte[] buffer = new byte[1024]; int length; while ((length = zipInputStream.read(buffer)) > 0) { fileOutputStream.write(buffer, 0, length); } fileOutputStream.close(); zipEntry = zipInputStream.getNextEntry(); } } catch (IOException iOException) { System.out.println("Failed to unzip the ''{0}'' file located in ''{1}'' folder. Due to, {2}"); } finally { // Validating if zipInputStream instance in not null if (zipInputStream != null) { try { zipInputStream.closeEntry(); zipInputStream.close(); } catch (IOException iOException) { } } } } /** * Traverse a directory from the source folder location and get all files, * and add the file into files list. * * @param node */ public static void generateFileList( String source, File node, List files) { // Validating if the node is a file if (node.isFile()) { files.add(generateZipEntry( source, node.getPath().toString())); } // Validating if the node is a directory if (node.isDirectory()) { String[] subNote = node.list(); for (String filename : subNote) { generateFileList(source, new File(node, filename), files); } } } /** * Format the file path to zip * @param source * @param file * @return */ private static String generateZipEntry(String source, String file) { return file.substring(source.length(), file.length()); } /** * * @param source * @param destination */ public static void zip(String source, String destination) { String method = "zip(String source, String destination)"; ZipOutputStream zipOutputStream = null; try { // Creating the zipOutputStream instance zipOutputStream = new ZipOutputStream( new FileOutputStream(destination)); List files = new ArrayList<>(); generateFileList(source, new File(source), files); // Iterating the list of file(s) to zip/compress for (String file : files) { // Adding the file(s) to the zip ZipEntry zipEntry = new ZipEntry(file); zipOutputStream.putNextEntry(zipEntry); FileInputStream fileInputStream = new FileInputStream( new StringBuilder(source).append(File.separator) .append(file).toString()); int length; byte[] buffer = new byte[1024]; while ((length = fileInputStream.read(buffer)) > 0) { zipOutputStream.write(buffer, 0, length); } // Closing the fileInputStream instance fileInputStream.close(); // De-allocating the memory by assigning the null value fileInputStream = null; } } catch (IOException iOException) { System.out.println("Failed to zip the file(s) located in ''{0}'' folder. Due to, {1}"); } finally { // Validating if zipOutputStream instance in not null if (zipOutputStream != null) { try { zipOutputStream.closeEntry(); zipOutputStream.close(); } catch (IOException iOException) { } } } } }