2012-12-09 50 views
3

您好我對zip格式很陌生,我使用Java的util實現來解壓縮一個文件,但是每次嘗試打開文件時都會拋出一個ZipException異常。我查看了文件是否損壞,這不是因爲我可以用winRar打開它。在Java中解壓縮錯誤

所以我繼續前進,並嘗試appache.commons.vfs包做同樣的事情,也導致失敗。

作爲最後的嘗試,我嘗試了庫7-zip-jbinding,它能夠讀取Zip存檔的內容,但我無法解壓縮它。

這裏是我的本地Java實現代碼:

BufferedOutputStream dest = null; 
    FileInputStream fis = new FileInputStream(archive); 
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis)); 
    ZipEntry entry; 
    File destFile; 

    destinationDir.mkdir(); 

    while ((entry = zis.getNextEntry()) != null) { 

     String currentfileName = entry.getName(); 
     destFile = new File(destinationDir, currentfileName); 
     File destinationParent = destFile.getParentFile(); 

     destinationParent.mkdirs(); 

     if (!entry.isDirectory()) { 
      int currentByte; 
      byte data[] = new byte[BUFFER_SIZE]; 

      FileOutputStream fos = new FileOutputStream(destFile); 
      dest = new BufferedOutputStream(fos, BUFFER_SIZE); 

      while ((currentByte = zis.read(data, 0, BUFFER_SIZE)) != -1) { 
       dest.write(data, 0, currentByte); 
      } 
      dest.flush(); 
      dest.close(); 

     } 
    } 
    fis.close(); 
    zis.close(); 

我的代碼appache公共VFS

public void unpack(final File outputDir,URI packLocation) throws IOException 
    { 
this.packLocation = packLocation; 
this.fileSystemManager = VFS.getManager(); 

outputDir.mkdirs(); 

    final FileObject packFileObject = fileSystemManager.resolveFile(packLocation.toString()); 
    try 
    { 
    final FileObject zipFileSystem = fileSystemManager.createFileSystem(packFileObject); 
    try 
    { 
     fileSystemManager.toFileObject(outputDir).copyFrom(zipFileSystem, new AllFileSelector()); 
    } 
    finally 
    { 
     zipFileSystem.close(); 
    } 
    } 
    finally 
    { 
    packFileObject.close(); 
    } 
} 

有什麼很明顯的,我很想念?如果有人使用7-zip-jbinding將文件解壓縮到文件系統中,請讓我知道它是如何完成的。

編輯1:

在執行該文件中的MAC終端解壓它給我下面的警告

警告:在開始或壓縮文件內的84個額外的字節。可這在某種程度上影響郵編輸入流?

編輯2:

在zip文件的extrabytes似乎把螺絲擰拉鍊輸入流..在終端上使用解壓示出被添加到zip文件額外的字節數。我用一個RandomAccessFile跳過(n)個字節和Zip輸入流開始工作正常..現在我需要做的是找到一種方法來刪除Zip文件中的額外字節..

編輯後的代碼粘貼在下面對於那些將來從中受益的人來說。

final int BUFFER_SIZE = 1024; 

    RandomAccessFile randomAccessFile = new RandomAccessFile(archive, "r"); 
    randomAccessFile.skipBytes(84); // The extra bytes 

    FileChannel channel = randomAccessFile.getChannel(); 

    BufferedOutputStream dest = null; 
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(Channels.newInputStream(channel))); 
    ZipEntry entry; 
    File destFile; 

    destinationDir.mkdir(); 

    while ((entry = zis.getNextEntry()) != null) { 

     String currentfileName = entry.getName(); 
     destFile = new File(destinationDir, currentfileName); 
     File destinationParent = destFile.getParentFile(); 

     destinationParent.mkdirs(); 

     if (!entry.isDirectory()) { 
      int currentByte; 
      byte data[] = new byte[BUFFER_SIZE]; 

      FileOutputStream fos = new FileOutputStream(destFile); 
      dest = new BufferedOutputStream(fos, BUFFER_SIZE); 
      while ((currentByte = zis.read(data, 0, BUFFER_SIZE)) != -1) { 
       dest.write(data, 0, currentByte); 
      } 
      dest.flush(); 
      dest.close(); 

     } 
    } 
    zis.close(); 

如果有人知道的方式來跳過額外的字節,我所有的耳朵:)

+0

檢查[this](http:// stackoverflow。com/questions/325202/java-util-zip-zipexception-error-in-opening-zip-file)post –

+0

這就是我第一篇文章,我看着..它沒有幫助..謝謝你指向我,雖然。 – Chris

回答

0

什麼是確切的異常信息?

請注意,ZIP文件可能存在格式差異。 例如:你使用加密嗎?這對於內置的java例程來說是個問題。

並且:您是否嘗試使用另一個ZIP工具重新包裝?

+0

異常是非常非常通用的。 'java.util.zip.ZipException:打開zip文件時出錯 at java.util.zip.ZipFile.open(ZipFile.java:0) at java.util.zip .ZipFile。 (ZipFile.java:127)」 沒有使用加密,但隨後被用於包裝的zip程序無意地增加了一些錯誤日誌中的相同流中.. 第三方工具如WINRAR跳過那些字節,但java的Zip輸入流不會,並認爲它的損壞。 查看此鏈接瞭解更多詳情。 [鏈接](https://github.com/Grandt/PHPZip/issues/3) – Chris

2

終於解決了這個問題,我的朋友的幫助下,

跳過空字節天真的辦法是堅持讀書,直到遇到「PK」的簽名。所以在程序中,一個輸入流讀取字節直到它遇到'PK',然後它初始化Zip inputStream並傳遞後面的字節流。

下面是快速和骯髒的方式。會有比這更優雅的解決方案..但目前這個工作。

InputStream zipStarterStream, emptyBytecountStream; 
    ZipInputStream zis; 
    int BUFFER = 2048; 

    /* Primary Checking to see if there is a zip file */ 
    File file = new File(filePath); 
    if (file.exists()) { 
     System.out.println("Zip found"); 
    } else { 
     System.out.println("Zip Not found"); 
     return; 
    } 
    try { 
     emptyBytecountStream = new FileInputStream(filePath); 
     Charset encoding = Charset.defaultCharset(); 
     Reader reader = new InputStreamReader(emptyBytecountStream, 
       encoding); 
     int r1, r2; 
     int charSkipped = 0; 
     boolean foundHeader = false; 

     // This is the check to skip the initial few bytes 

     while ((r1 = reader.read()) != -1 && (r2 = reader.read()) != -1) { 
      char ch1 = (char) r1; 
      char ch2 = (char) r2; 
      if (ch1 == 'P' && ch2 == 'K') { 
       foundHeader = true; 
       break; 
      } 
      charSkipped += 2; 
     } 
     emptyBytecountStream.close(); 

     zipStarterStream = new FileInputStream(filePath); 
     zis = new ZipInputStream(new BufferedInputStream(zipStarterStream)); 

     if (foundHeader && charSkipped > 0) { 
      zipStarterStream.skip(charSkipped); 
     } 

     String outputPath = getPublicStorageDir("") 
       + "/" 
       + filePath.substring(filePath.lastIndexOf("/") + 1, 
         filePath.length()); 

     new File(outputPath).mkdir(); 
     ZipEntry entry; 

     while ((entry = zis.getNextEntry()) != null) { 

      String currentfileName = entry.getName(); 
      File destFile = new File(outputPath, currentfileName); 
      File destinationParent = destFile.getParentFile(); 

      destinationParent.mkdirs(); 

      if (!entry.isDirectory()) { 
       int currentByte; 
       byte data[] = new byte[BUFFER]; 

       // write the current file to disk 
       FileOutputStream fos = new FileOutputStream(destFile); 
       BufferedOutputStream dest = new BufferedOutputStream(fos, 
         BUFFER); 

       // read and write until last byte is encountered 
       while ((currentByte = zis.read(data, 0, BUFFER)) != -1) { 
        dest.write(data, 0, currentByte); 
       } 
       dest.flush(); 
       dest.close(); 
      } 

      if (currentfileName.endsWith(".zip")) { 
       extractZipFolder(destFile.getAbsolutePath()); 
      } 
     } 
     zis.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 

    } 
+0

存在一個通用的解決方案:[如何讀取自解壓縮的exe-zip文件](http://stackoverflow.com /問題/ 7924895 /如何-可以-I-讀從-A-的WinZip自解壓-EXE-zip文件,在-JAVA) –