Creazione di un archivio zip in Java

Ho un file creato dal programma 7zip. Ho usato il metodo deflate per comprimerlo. Ora voglio creare lo stesso archivio (con lo stesso MD5sum) in java . Quando creo il file zip, ho usato l’algoritmo che ho trovato su Internet, ad esempio http://www.kodejava.org/examples/119.html, ma quando ho creato il file zip con questo metodo la dimensione compressa è superiore alla dimensione di il file non compresso, quindi cosa sta succedendo? Questa non è una compressione molto utile. Quindi, come posso creare il file zip che è esattamente lo stesso del file zip che ho creato con il programma 7zip? Se aiuta ho tutte le informazioni sul file zip che ho creato nel programma 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(); } } 

Giusto per chiarire, hai usato l’algoritmo ZIP in 7zip per il tuo originale? Inoltre 7zip afferma di avere un rapporto di compressione 2-10% migliore rispetto ad altri fornitori. Mi azzarderei a pensare che l’algoritmo ZIP integrato in Java non sia così ottimizzato come quello di 7zip. La cosa migliore è invocare 7zip dalla riga di comando se si desidera un file compresso in modo simile.

Stai provando a decomprimere un file ZIP, cambiare un file al suo interno, quindi ricomprimerlo in modo che abbia lo stesso hash MD5? Gli Hash servono a impedirti di farlo.

ZipOutputStream ha pochi metodi per ottimizzare la compressione:

public void setMethod (metodo int)

Imposta il metodo di compressione predefinito per le voci successive. Questo valore predefinito verrà utilizzato ogni volta che il metodo di compressione non viene specificato per una singola voce del file ZIP e inizialmente impostato su DEFLATED.

public void setLevel (int level)

Imposta il livello di compressione per le voci successive che sono DEFLATED. L’impostazione predefinita è DEFAULT_COMPRESSION. livello – il livello di compressione (0-9)

Quando aggiungi qualcosa come:

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

non migliora la tua compressione?

Ecco una funzione che si passa al percorso assoluto che creerà un file zip con lo stesso nome della directory (sotto il quale si desidera zippare tutta la sottocartella e i file, tutto !!) e restituirà true in caso di successo e falso in caso di eccezione se ce ne sono

 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; } } 

Per generare due file zip identici (incluso md5sum identici) dallo stesso file sorgente, ti consiglio di utilizzare la stessa utility zip, che utilizza sempre lo stesso programma Java o usa sempre 7zip.

L’utilità 7zip, ad esempio, ha molte opzioni, molte delle quali sono semplici impostazioni predefinite che possono essere personalizzate (o diverse tra versioni?) – e qualsiasi implementazione Java zip dovrebbe anche impostare esplicitamente queste opzioni. Se la tua app Java può semplicemente richiamare un programma “7z” esterno, probabilmente otterrai comunque prestazioni migliori rispetto a un’implementazione zip Java personalizzata. (Questo è anche un buon esempio di un problema di riduzione della mappa in cui è ansible ridimensionare facilmente l’implementazione.)

Ma il problema principale che incontrerai se hai un file zip generato lato server e un file zip generato lato client è che il file zip memorizza due cose oltre al solo file originale: (1) il nome del file, e (2) il timestamp del file. Se uno di questi è cambiato, il file zip risultante avrà un diverso MD5:

 $ 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 

Ma, usando “cp -p” (conserva 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 

Troverai lo stesso problema con nomi di file e percorsi diversi, anche quando i file all’interno dello zip sono identici.

 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(); } } } 

Si prega di trovare nel codice seguente con le funzionalità per zip e decomprimere . Spero che possa aiutare qualcuno.

 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) { } } } } }