Créer une archive zip en Java

J’ai un fichier créé par le programme 7zip. J’ai utilisé une méthode de dégonflage pour le compresser. Maintenant, je veux créer la même archive (avec le même MD5sum) en java . Lorsque je crée un fichier zip, j’ai utilisé l’algorithme que j’ai trouvé sur Internet par exemple http://www.kodejava.org/examples/119.html mais lorsque j’ai créé un fichier zip avec cette méthode, la taille compressée est supérieure à la taille de le fichier non compressé alors que se passe-t-il? Ce n’est pas une compression très utile. Alors, comment puis-je créer un fichier zip qui est exactement le même que le fichier zip que j’ai créé avec le programme 7zip? Si cela aide, j’ai toutes les informations sur le fichier zip que j’ai créé dans le programme 7zip.

 // simplified code for zip creation in java import java.io.*; import java.util.zip.*; public class ZipCreateExample { public static void main(Ssortingng[] 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(); } } 

Juste pour clarifier, vous avez utilisé l’algorithme ZIP dans 7zip pour votre original? Aussi, 7zip prétend avoir un taux de compression de 2 à 10% supérieur à celui des autres fournisseurs. Je suppose que l’algorithme ZIP intégré à Java n’est pas aussi optimisé que celui de 7zip. Le mieux est d’appeler 7zip à partir de la ligne de commande si vous voulez un fichier compressé de la même manière.

Essayez-vous de décompresser un fichier ZIP, de modifier un fichier à l’intérieur de celui-ci, puis de le recompresser afin qu’il ait le même hachage MD5? Les hachages sont destinés à vous empêcher de le faire.

ZipOutputStream a peu de méthodes pour régler la compression:

public void setMethod (méthode int)

Définit la méthode de compression par défaut pour les entrées suivantes. Cette valeur par défaut sera utilisée chaque fois que la méthode de compression n’est pas spécifiée pour une entrée de fichier ZIP individuelle et est initialement définie sur DEFLATED.

public void setLevel (niveau int)

Définit le niveau de compression pour les entrées suivantes qui sont DEFLATED. Le paramètre par défaut est DEFAULT_COMPRESSION. level – le niveau de compression (0-9)

Lorsque vous ajoutez après quelque chose comme:

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

cela n’améliore-t-il pas votre compression?

Voici une fonction que vous passez le chemin absolu, il va créer un fichier zip avec le même nom que le répertoire (sous lequel vous voulez zip de tous les sous-dossiers et fichiers, tout !!) et retourner true en cas de succès et false en exception si seulement.

 public class FileUtil { final static int BUFFER = 2048; private static Logger log = Logger.getLogger(FileUtil.class); public static boolean createZipArchive(Ssortingng 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); Ssortingng subdirList[] = subDir.list(); for(Ssortingng sd:subdirList) { // get a list of files from current directory File f = new File(srcFolder+"/"+sd); if(f.isDirectory()) { Ssortingng 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; } } 

Pour générer deux fichiers zip identiques (y compris md5sum identique) à partir du même fichier source, je vous recommande d’utiliser le même utilitaire zip – utilisez toujours le même programme Java ou utilisez toujours 7zip.

L’utilitaire 7zip par exemple a beaucoup d’options – dont beaucoup sont simplement des valeurs par défaut qui peuvent être personnalisées (ou différentes entre les versions?) – et toute implémentation Java zip devrait également définir ces options explicitement. Si votre application Java peut simplement appeler un programme “7z” externe, vous obtiendrez de toute façon de meilleures performances qu’une implémentation Java personnalisée. (Ceci est aussi un bon exemple de problème de réduction de carte où vous pouvez facilement augmenter la mise en œuvre.)

Mais le problème principal que vous rencontrerez si vous avez un fichier zip généré côté serveur et un fichier zip généré par le client est que le fichier zip stocke deux choses en plus du fichier d’origine: (1) le nom du fichier et (2) l’horodatage du fichier. Si l’un ou l’autre a changé, le fichier zip résultant aura un md5sum différent:

 $ 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 

Mais, en utilisant “cp -p” (conserve l’horodatage):

 $ 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 

Vous trouverez le même problème avec différents noms de fichiers et chemins, même lorsque les fichiers contenus dans le fichier zip sont identiques.

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

Veuillez trouver dans le code ci-dessous les fonctionnalités pour décompresser et décompresser . J’espère que cela peut aider quelqu’un.

 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(Ssortingng source, Ssortingng destination) { Ssortingng method = "unZip(Ssortingng source, Ssortingng 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) { Ssortingng fileName = zipEntry.getName(); File file = new File(new SsortingngBuilder(destination) .append(File.separator) .append(AppUtil.getFileNameWithoutExtension( AppUtil.getNameFromPath(source))) .append(File.separator).append(fileName).toSsortingng()); // 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( Ssortingng source, File node, List files) { // Validating if the node is a file if (node.isFile()) { files.add(generateZipEntry( source, node.getPath().toSsortingng())); } // Validating if the node is a directory if (node.isDirectory()) { Ssortingng[] subNote = node.list(); for (Ssortingng filename : subNote) { generateFileList(source, new File(node, filename), files); } } } /** * Format the file path to zip * @param source * @param file * @return */ private static Ssortingng generateZipEntry(Ssortingng source, Ssortingng file) { return file.subssortingng(source.length(), file.length()); } /** * * @param source * @param destination */ public static void zip(Ssortingng source, Ssortingng destination) { Ssortingng method = "zip(Ssortingng source, Ssortingng 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) { } } } } }