2016-02-25 77 views
2

我試圖將目錄從一個區域(sdCard/someFolder)壓縮到第二個目錄(sdCard/Download),直到.zip文件大小變爲5mb。然後,我想創建一個新的.zip文件,填充新文件到5mb等。在Android中使用ZipOutputStream將最多24MB文件壓縮爲.zip

當前,我的代碼成功將文件壓縮到.zip目錄,但其中一個.zip目錄始終損壞。當我的for循環退出22 objects的第一個Files[]並開始下一個目錄Files[]4 objects時,我看到了這個。我相信我正在失去一些舊的OutputStreams清理。在for循環的第二次嘗試後,out.putNextEntry()變爲空。任何幫助就足夠了。

private static void addDirToArchive(ZipOutputStream out, FileOutputStream destinationDir, File sdCardMNDLogs) 
{ 
    File[] listOfFiles = sdCardMNDLogs.listFiles(); 

    BufferedInputStream origin = null; 

    Log.i(TAG3, "Reading directory: " + sdCardMNDLogs.getName()); 

    try{ 

    byte[] buffer = new byte[BUFFER]; 
    for(int i = 0; i < listOfFiles.length; i++) 
    { 
     if(listOfFiles[i].isDirectory()) 
     { 
      addDirToArchive(out, destinationDir, listOfFiles[i]); 
      continue; 
     } 
     try 
     { 
      FileInputStream fis = new FileInputStream(listOfFiles[i]); 
      origin = new BufferedInputStream(fis,BUFFER); 
      ZipEntry ze = new ZipEntry(listOfFiles[i].getName()); 

      if(currentZipFileSize >= EMAIL_SIZE) 
      { 
       out.close(); 
       Log.d(emailTAG, "Creating new zipfile: /Download/MND/nwdLogs_" + i); 
       out = new ZipOutputStream(new FileOutputStream(new File(sdCard.getAbsolutePath() + "/Download/MND/nwdLogs_ " + i + ".zip"))); 
       currentZipFileSize = 0; 
      } 
      out.putNextEntry(ze); 
      int length; 
      Log.i(TAG3, "Adding file: " + listOfFiles[i].getName()); 
      while((length = origin.read(buffer, 0, BUFFER)) != -1) 
      { 
       out.write(buffer, 0, length); 
      } 
      out.closeEntry(); 
      origin.close(); 
      currentZipFileSize = currentZipFileSize + ze.getCompressedSize(); 
     } 
     catch(IOException ioe) 
     { 
      Log.e(TAG3, "IOException: " + ioe); 
     } 
    } 
    } 
    finally 
    { 
     try { 
      out.close(); 
    } catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
} 

}

FileOutputStream destinationDir = new FileOutputStream(sdCard.getAbsolutePath() + "/Download/Dir/nwdLogs.zip"); 
ZipOutputStream out = new ZipOutputStream(destinationDir); 

currentZipFileSize = 0; 
addDirToArchive(out, destinationDir, dirName); 
out.close(); 
destinationDir.close(); 

回答

2

我懷疑的問題是,你是不是打開一個ZIP文件之前調用out.close()。我的理解是,ZIP的索引只寫在ZIP關閉時,所以如果你忽略關閉索引將會丟失:因此腐敗。

此外,請注意,您無需關閉fisorigin。只需關閉origin ...並關閉fis


UPDATE - 當你已經解決了原來緊密的bug,還有更多:

  1. 您已經添加了一個finally塊關閉out。那是錯的。您不希望addDirToArchive關閉out。這是你例外的可能原因。

  2. 有一對夫婦的問題,這種情況發生,你這樣做了之後:

    if (currentZipFileSize >= EMAIL_SIZE) 
        { 
         out.close(); 
         out = new ZipOutputStream(new FileOutputStream(...)); 
         currentZipFileSize = 0; 
        } 
    

    由於out是本地參數,調用者沒有看到你做出改變 。因此:

    • 當你在呼出的電話out.close(),你可能會被關閉 原來的ZIP(已關閉)......不是當前

    • ,如果你叫addDirToArchive(out, destinationDir, dirName) 多次,在隨後的調用可能會傳遞一個封閉的ZIP文件。

  3. 您的異常處理被誤導(IMO)。如果在ZIP中寫入文件時發生I/O錯誤,則不需要記錄消息並繼續。你想要救助。無論是完全崩潰的應用程序,或停止做你在做什麼。在這種情況下,你「流被關閉」顯然是你的代碼中的一個bug,你的異常處理有效地告訴應用程序忽略它。

幾點建議:

  • 如果要拆分開的責任就可以選擇你需要非常小心什麼樣的代碼具有用於封閉怎樣的責任多種方法關閉資源。你需要了解你在做什麼。

  • 盲目應用(所謂的)「解決方案」(如finally的東西)......'有人說「XXX是最佳做法」或「總是做XXX」......會讓你陷入困境。您需要1)瞭解「解決方案」的作用,2)認爲關於解決方案是否實際滿足您的需求。

+0

我在創建新的ZipOutputStream之前以及在初始調用addDirToArchive(out,destinationDir,dirName)之前缺少out.close()。謝謝。 –

+0

現在我遇到了包含兩個文件夾和兩個文件的原始目錄不能正確讀取的問題。該程序將壓縮文件[]中的第一個目錄,但由於錯誤而未壓縮其他三個目錄:流被關閉。 –

相關問題