2012-06-19 80 views
2

我需要在java(用於android應用程序)中編寫算法以讀取包含更多文件夾以及每個包含圖像和音頻文件的文件夾,因此結構是這樣的:mainDir/categorySubfolder/myFile1.jpg如何創建具有最大文件大小限制的java zip存檔

我的問題是,我需要將存檔的大小限制爲16mb,並且在運行時根據需要創建儘可能多的存檔以包含我的主mainDir文件夾中的所有文件。

我嘗試了幾個來自網絡的例子,並且我閱讀了java文檔,但是我無法理解並按照需要將它們放在一起。有人以前做過這個,或者有一個鏈接或一個例子嗎?

我解決了用遞歸方法讀取文件的問題,但我無法編寫用於創建zip的邏輯。

我很樂意提供建議或更好的工作示例。

+0

你從網上試過的一些例子是什麼?當你嘗試他們時發生了什麼? –

+0

http://stackoverflow.com/questions/11084823/filenotfoundexception-no-such-file-or-directory這是我的第一篇文章,有一個錯誤,我現在修復了,但現在2更多的出現....第一個是我似乎無法設置ZipEntry的大小,第二個是,當我嘗試提取文件時,我得到的錯誤'不支持壓縮方法' – androidu

+0

也因爲我無法設置ZipEntry的大小我的邏輯不起作用,因此它總是隻創建一個存檔 – androidu

回答

4

zip4j改善是可以創建多部分的zip文件一個偉大的圖書館。

net.lingala.zip4j.core.ZipFile zipFile = new ZipFile("out.zip"); 
ZipParameters parameters = new ZipParameters(); 
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); 
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); 
zipFile.createZipFileFromFolder("path/to/source/dir", parameters, true, maximum size); 

你可以在他們的網站上找到更多的例子。

1

據我所見,How to split a huge zip file into multiple volumes?只是建議跟蹤檔案大小到目前爲止,當它接近某個任意值(應該低於最大值)時,它會決定開始一個新文件。因此,對於16MB的限制,您可以將該值設置爲10MB,並在達到此限制時啓動一個新的zip,但如果您達到9MB,並且您的下一個文件將縮小到8MB,則最終的zip將超過限制。

在這篇文章中給出的代碼似乎並不適用於我,因爲1)它在創建ZipEntry之前獲得了大小,所以它始終是0和2)它沒有寫出任何zip :-)如果我弄錯了 - 讓我知道。

以下適用於我。爲了簡單起見,我已經將它從Wrapper中取出,並將它全部放在main(String args [])中。還有很多,很多方面該代碼可:-)

import java.util.zip.*; 
import java.io.*; 



    public class ChunkedZipTwo { 

     static final long MAX_LIMIT=10 * 1000 * 1024; //10MB limit - hopefully this 


     public static void main(String[] args) throws Exception {  


      String[] files = {"file1", "file2", "file3"}; 
      int i = 0; 
      boolean needNewFile = false; 
      long overallSize = 0; 
      ZipOutputStream out = getOutputStream(i); 
      byte[] buffer = new byte[1024]; 

      for (String thisFileName: files) { 


        if (overallSize > MAX_LIMIT) { 
         out.close(); 
         i++; 
         out = getOutputStream(i); 
         overallSize=0; 
        } 

        FileInputStream in = new FileInputStream(thisFileName); 
        ZipEntry ze = new ZipEntry(thisFileName); 
        out.putNextEntry(ze); 
        int len; 
        while ((len = in.read(buffer)) > 0) { 
         out.write(buffer, 0, len); 
        } 
        out.closeEntry(); 
        in.close(); 
        overallSize+=ze.getCompressedSize(); 




      } 
      out.close();  
     } 

     public static ZipOutputStream getOutputStream(int i) throws IOException { 
      ZipOutputStream out = new ZipOutputStream(new FileOutputStream("bigfile" + i +".zip")); 
      out.setLevel(Deflater.DEFAULT_COMPRESSION); 
      return out; 
     } 
} 
+0

我一定會試試這個:)是的,你是對的。我從我的示例代碼中獲得了相同的行爲。我會回來看看我的結果:D謝謝 – androidu

+0

謝謝,我對代碼進行了一些小的修改,以實現我想要的結果! :D – androidu

+1

沒問題,你有什麼改變? –

1

我正在使用下面的代碼/類來分割和壓縮大量/大小的文件。 我已經測試這個類上下面

  • 數目的未壓縮的文件:116
  • 總大小(未壓縮):29.1 GB
  • ZIP文件大小限制(各):3 GB [MAX_ZIP_SIZE]
  • 總大小(壓縮):7.85 GB(splited爲MAX_ZIP_SIZE
  • 數ZIP文件的:3

你必須的MAX_ZIP_SIZE值更改爲16(MB)* 1024 * 1024 = 16777216-22(拉鍊頭的大小)= 。
在我的代碼中,MAX_ZIP_SIZE設置爲3 GB(ZIP has limitation of 4GB on various things)。

final long MAX_ZIP_SIZE = 3221225472L; // 3 GB

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipOutputStream; 

public class QDE_ZIP { 

    public static String createZIP(String directoryPath, String zipFileName, String filesToZip) { 
     try { 
      final int BUFFER = 104857600; // 100MB 
      final long MAX_ZIP_SIZE = 3221225472L; //3 GB 
      long currentSize = 0; 
      int zipSplitCount =0; 
      String files[] = filesToZip.split(","); 
      if (!directoryPath.endsWith("/")) { 
       directoryPath = directoryPath + "/"; 
      } 
      byte fileRAW[] = new byte[BUFFER]; 
      ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(directoryPath + zipFileName.toUpperCase())); 
      ZipEntry zipEntry; 
      FileInputStream entryFile; 
      for (String aFile : files) { 
       zipEntry = new ZipEntry(aFile); 
       if (currentSize >= MAX_ZIP_SIZE) 
       { 
        zipSplitCount ++; 
        //zipOut.closeEntry(); 
        zipOut.close(); 
        zipOut = new ZipOutputStream(new FileOutputStream(directoryPath + zipFileName.toLowerCase().replace(".zip", "_"+zipSplitCount+".zip").toUpperCase())); 
        currentSize = 0; 
       } 
       zipOut.putNextEntry(zipEntry); 
       entryFile = new FileInputStream(directoryPath + aFile); 

       int count; 
       while ((count = entryFile.read(fileRAW, 0, BUFFER)) != -1) { 
        zipOut.write(fileRAW, 0, count); 

        //System.out.println("number of Bytes read = " + count); 
       } 
       entryFile.close(); 
       zipOut.closeEntry(); 
       currentSize += zipEntry.getCompressedSize(); 
      } 

      zipOut.close(); 
      //System.out.println(directory + " -" + zipFileName + " -Number of Files = " + files.length); 
     } catch (FileNotFoundException e) { 
      return "FileNotFoundException = " + e.getMessage(); 
     } catch (IOException e) { 
      return "IOException = " + e.getMessage(); 
     } catch (Exception e) { 
      return "Exception = " + e.getMessage(); 
     } 

     return "1"; 
    } 

} 

我回來了所有異常消息作爲字符串來使用它。這個 我自己的案例與項目有關。

相關問題