2016-04-15 42 views
2

我使用AsyncTask解压缩文件,并且一切似乎都进行得很顺利(ZIP压缩文件中的所有文件都被解压缩),但是我的解压缩方法从未完成。使用ZipInputStream解压缩永不结束

下面是我解压类的源:

public class MyUnzipper { 


    public static boolean unzipFileIntoDirectory(String inputFilename, String outputPath) throws Exception { 
     ZipInputStream zis = null; 
     BufferedOutputStream dest = null; 

     try { 
      File archive = new File(inputFilename); 
      File destinationDir = new File(outputPath); 

      final int BUFFER_SIZE = 1024; 

      zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(archive), BUFFER_SIZE)); 
      ZipEntry entry = null; 
      File destFile; 
      while((entry = zis.getNextEntry()) != null){ 

       destFile = new File(destinationDir, entry.getName()); 

       if(entry.isDirectory()){ 
        destFile.mkdirs(); 
       } 
       else { 
        // check for and create parent directories if they don't exist 
        File parentDir = destFile.getParentFile(); 
        if (null != parentDir) { 
         if (!parentDir.isDirectory()) { 
          parentDir.mkdirs(); 
         } 
        } 

        int count; 
        byte data[] = new byte[BUFFER_SIZE]; 
        dest = new BufferedOutputStream(new FileOutputStream(destFile), BUFFER_SIZE); 
        Log.i("MyUnzipper", "Beginning unzip of " + destFile); 

        while((count = zis.read(data, 0, BUFFER_SIZE)) != -1){ 
         dest.write(data, 0, count); 
         Log.v("MyUnzipper", "Count = " + count); 
        } 
        dest.flush(); 
        dest.close(); 
        dest = null; 
       } 

       zis.closeEntry(); 

       Log.wtf("MyUnzipper", "Unzipped entry " + entry.getName()); 
      } 

      Log.wtf("MyUnzipper", "Unzip done"); 
     } 
     catch(Exception e){ 
      Log.wtf("MyUnzipper", "Unzip error"); 
      e.printStackTrace(); 
      return false; 
     } 
     finally { 
      if(null != zis) 
       zis.close(); 

      if(null != dest) 
       dest.close(); 
     } 

     return true; 
    } 

} 

当我调试此行由行,它运行良好,直到它解压缩所有文件,然后它得到zis.closeEntry(),只是调试器“消失“,即下一行(Log.wtf(...))永远不会执行。我的AsyncTask从来没有完成,就好像我陷入了无限循环?!但是看看ZipInputStream.closeEntry()的来源,似乎没有任何循环或任何可疑的东西?

我也曾尝试提取使用ZipFile代替ZipInputStream ZIP档案,但后来我得到以下错误:

java.util.zip.ZipException: End Of Central Directory signature not found 

没有什么错的ZIP文件,我曾与zip -v -T在Mac上测试它OSX。我也尝试使用ZIP版本3.0和2.1重新压缩它(原始版本是2.0)。我可以在Mac OSx上解压所有版本,而不会出现任何问题(使用Unarchiver和Archive Utility)。

这使我疯了,有什么可能是错的?

 

更新(解决)

可谓是一个非常愚蠢的问题,没有真正涉及到解压。

我从服务器下载的ZIP文件解压缩在他们面前,显然我忘了在开始解压缩操作之前,请从下载操作输出流close()

也许这个线程可以帮助别人谁犯了同样的愚蠢的错误。

+0

'字符串名称= entry.getName(); zis.closeEntry(); Log.wtf(.... name);'也许?不知道。 –

+0

问题是执行永远不会到达最后一个文件的'Log.wtf(...)',它总是不会超过'closeEntry()'...因此只输出前11个文件的名字。 – BadCash

+1

你使用的是Android [ZipInputStream](https://developer.android.com/reference/java/util/zip/ZipInputStream.html)吗?Apache Commons中的[ZipArchiveInputStream](https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.html)可能适用于您的情况。 –

回答

4

那么,即使您关闭所有以前的输出和输入流,您的ZIP解压缩代码有时也会卡住。而且,这是a known bugZipInputStream#read可以返回0

增加:

如果您的ZIP文件包含非ACSII文件名某些文件,您可以用提取面临的问题。 Android的ZipInputStream不适用于UTF-8,CP437等。

在这种情况下Apache的百科全书应该是一个解决方案:

private boolean unpack(File zipFile, File targetDir) { 
    ZipFile zip = null; 
    try { 
     zip = new ZipFile(zipFile.getAbsoluteFile()); 
     final Enumeration<ZipArchiveEntry> entries = zip.getEntries(); 
     while(entries.hasMoreElements()) { 
      ZipArchiveEntry entry = entries.nextElement(); 
      if (entry.isDirectory()) { 
       mkdirsOrThrow(new File(targetDir, entry.getName())); 
       continue; 
      } 
      final File entryDestination = new File(targetDir, entry.getName()); 
      mkdirsOrThrow(entryDestination.getParentFile()); 
      final InputStream in = zip.getInputStream(entry); 
      final OutputStream out = new FileOutputStream(entryDestination); 
      IOUtils.copy(in, out); 
      IOUtils.closeQuietly(in); 
      IOUtils.closeQuietly(out); 
     } 
    } catch (IOException e) { 
     throw new RuntimeException(e); 
    } finally { 
     if (zip!= null) try { 
      zip.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    return true; 
}