2011-01-23 2 views
31

У меня есть один файл, созданный программой 7zip. Я использовал deflate способ сжать его. Теперь я хочу создать тот же архив (с тем же MD5sum) в java. Когда я создаю zip-файл, я использовал алгоритм, который я нашел в Интернете, например, http://www.kodejava.org/examples/119.html, но когда я создал zip-файл с этим методом, сжатый размер больше, чем размер несжатого файла, так что происходит? Это не очень полезное сжатие. Итак, как я могу создать zip-файл, который точно такой же, как zip-файл, который я создал с помощью программы 7zip? Если это помогает, у меня есть вся информация о zip-файле, который я создал в программе 7zip.Создание zip-архива в Java

ответ

57
// 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(); 
    } 
} 
+0

Я не могу открыть ZIP-папку, он говорит, что доступ к сжатой папке отклонен –

4

Чтобы уточнить, вы использовали алгоритм ZIP в 7zip для своего оригинала? Кроме того, 7zip утверждает, что коэффициент сжатия более 2-10% по сравнению с другими поставщиками. Я бы рискнул предположить, что встроенный в Java алгоритм ZIP не так оптимизирован, как тот, что в 7zip. Лучше всего вызывать 7zip из командной строки, если вы хотите аналогично сжатый файл.

Вы пытаетесь распаковать ZIP-файл, изменить файл в нем, а затем повторно сжать его так, чтобы он имел тот же MD5-хэш? Хэши предназначены для того, чтобы помешать вам это сделать.

+0

Кроме того, при сжатии с 7zip имеется множество опций. Даже при непосредственном вызове 7zip вам все равно придется угадать конфигурацию, которая была использована. – Cephalopod

+0

Я стараюсь много конфигурации, но все еще сжатый размер был точно таким же, как несжатый размер или ниже, но не выше – hudi

+0

hm и как я могу вызвать 7zip из командной строки? можете ли вы привести мне пример – hudi

5

ZipOutputStream имеет несколько методов для сжатия мелодии:

public void setMethod(int method)

Устанавливает метод сжатия по умолчанию для последующих записей. Это значение по умолчанию будет использоваться всякий раз, когда метод сжатия не указан для отдельной записи ZIP-файла и имеет значение , первоначально установленное на DEFLATED.

public void setLevel(int level)

Устанавливает уровень сжатия для последующих записей, которые спущены. По умолчанию используется значение DEFAULT_COMPRESSION. уровень - уровень сжатия (0-9)

Когда вы добавляете после что-то вроде:

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

это не улучшает ваше сжатие?

+0

, как я уже говорил, прежде чем использовать дефлированный метод, а также пробую весь уровень сжатия (-1 .. 9), но все равно ничего не изменилось. – hudi

1

Для создания двух идентичных архивных файлов (в том числе идентичных md5sum) из того же исходного файла, я бы рекомендовал использовать ту же самую программу зип - либо всегда использовать ту же самую программу Java, или всегда использовать 7zip.

7zip утилиты, например, имеет много вариантов - многие из которых просто по умолчанию, которые могут быть настроены (или различающимся между релизами?) - и любой реализацией Java зип бы также установить эти параметры в явном виде , Если ваше Java-приложение может просто вызывать внешнюю программу «7z», вы, вероятно, получите лучшую производительность, чем обычная реализация Java-zip. (Это также хороший пример проблемы с уменьшением карты, где вы можете легко масштабировать реализацию.)

Но основная проблема, с которой вы столкнетесь, если у вас есть созданный на стороне сервера zip-файл и клиентская сторона созданный zip-файл, состоит в том, что zip-файл хранит две вещи в дополнение к только исходному файлу: (1) имя файла и (2) метку времени файла.Если какая-либо из них изменились, то результирующий почтовый файл будет иметь другой md5sum:

$ 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 

Но, используя «ф -p» (сохранить метку времени):

$ 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 

Вы найдете такая же проблема с разными именами файлов и путями, даже если файлы внутри zip идентичны.

4

Вот функция, по которой вы передаете абсолютный путь, она создаст zip-файл с тем же именем, что и каталог (под которым вы хотите сделать zip всей подпапки и файлов, все!) И вернуть true при успешном завершении а false - исключение, если оно есть.

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

Пожалуйста, найдите в коде ниже, имеющего функциональные возможности почтовый и разархивировать. Надеюсь, это может помочь кому-то.

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