2013-02-03 156 views
0

我已經編寫了一個解壓縮ZIP壓縮文件的程序,然後遞歸解壓縮或提取壓縮文件中找到的壓縮文件。 ZIP中的檔案可能是tar或ZIP檔案,我可以將它們提取得很好。如何使用Java中的Commons Compress解壓縮後刪除ZIP存檔?

在提取某個新目錄中的內部存檔後,我想刪除它們。這對於tar檔案來說工作得很好,但由於某些原因,它不適用於ZIP檔案。我關閉了所有流,並且應該刪除失敗,我使用deleteOnExit作爲失敗保護,但這也不起作用。

try (ArchiveInputStream ais = 
     asFactory.createArchiveInputStream(
      new BufferedInputStream(
      new FileInputStream(archive)))) { 

     System.out.println("Extracting!"); 
     ArchiveEntry ae; 
     while ((ae = ais.getNextEntry()) != null) { 
      if (ae.isDirectory()) { 
       File dir = new File(archive.getParentFile(), ae.getName()); 
       dir.mkdirs(); 
       continue; 
      } 

      File f = new File(archive.getParentFile(), ae.getName()); 
      File parent = f.getParentFile(); 
      parent.mkdirs(); 
      try (OutputStream os = new FileOutputStream(f)) { 
       IOUtils.copy(ais, os); 
       os.close(); 
      } catch (IOException innerIoe) { 
       ... 
      } 
     } 

     ais.close(); 
     if (!archive.delete()) { 
      System.out.printf("Could not remove archive %s%n", 
           archive.getName()); 
      archive.deleteOnExit(); 
     } 
    } catch (IOException ioe) { 
     ... 
    } 

應該沒有開放的流,除非關閉ArchiveInputStream不會實際關閉流。但這又適用於tar檔案。

我在某處讀到一個地方,可以刪除調用父文件上的listFiles()並找到ZIP存檔並刪除它的ZIP存檔,但這聽起來像是一個奇怪的複雜過程。必須有一些更簡單的方法。

編輯:

的問題是特定於Windows。在Linux上(SliTaz 4和Red Hat Enterprise 5),這個工作非常好。這告訴我,Windows以某種方式鎖定ZIP檔案,這似乎有點奇怪。

+0

您應該使用'try-finally'語句來確保在發生異常時發生流關閉。 – Vulcan

+0

檢查'.mkdirs()'和朋友,他們可能會自動失敗 - 這就是爲什麼如果使用Java 7而不是'File'則應該使用'Files' API。 – fge

+0

@Vulcan我將它切換到試用資源。但沒有區別。 @fge使用'Files'和'Path',它告訴我該文件正在被另一個進程使用(這可能意味着程序本身)。但即使使用'deleteOnExit'也沒有效果,這讓我覺得該文件可能正在被操作系統使用(我現在正在Windows上運行它,但我明天會在Linux上嘗試它)。如果'mkdirs'失敗或我將其刪除,則在提取時創建的文件上會出現I/O異常。 – Sardtok

回答