2016-04-15 9 views
2

Ich benutze eine AsyncTask, um eine Datei zu entpacken, und alles scheint gut zu laufen (alle Dateien im ZIP-Archiv werden extrahiert), aber meine Methode entpacken nie beendet.Entpacken mit ZipInputStream endet nie

Hier ist die Quelle für meine unzip Klasse:

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; 
    } 

} 

Wenn ich diese Zeile-für-Zeile debuggen, es läuft gut, bis es alle Dateien entpackt hat, dann wird es zu zis.closeEntry() und der Debugger nur " geht weg ", dh die nächste Zeile (Log.wtf(...)) wird nie ausgeführt. Meine AsyncTask ist nie fertig, es ist so, als ob ich in einer Endlosschleife stecke. Aber wenn man sich die Quelle für ZipInputStream.closeEntry() ansieht, scheint es dort keine Schleifen oder etwas Verdächtiges zu geben? mit ZipFile statt ZipInputStream

Ich habe auch versucht, das ZIP-Archiv zu extrahieren, aber dann bekomme ich folgende Fehlermeldung:

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

Es gibt nichts falsch mit der ZIP-Datei ist, habe ich es mit zip -v -T auf Mac getestet OSx. Ich habe auch versucht, es mit ZIP Version 3.0 und 2.1 (Original war 2.0) neu zu zippen. Ich kann unter Mac OSx alle Versionen ohne Probleme entpacken (mit dem Unarchiver und Archive Utility).

Das macht mich verrückt, was kann möglicherweise falsch sein?

 

Update (gelöst)

stellt sich heraus, ein wirklich dummes Problem zu sein, nicht wirklich auf die unzipping bezogen.

Ich lade die ZIP-Dateien von einem Server, bevor ihnen das Entpacken und anscheinend habe ich vergessen close() auf dem Ausgabestrom rufen aus dem Download-Vorgang vor dem Entpacken Betrieb starten.

Vielleicht kann dieser Thread jemandem helfen, der den gleichen dummen Fehler macht.

+0

'String name = entry.getName();:

In diesem Fall sollte Apache Commons eine Lösung sein zis.closeEntry(); Log.wtf (.... name); 'vielleicht? Keine Ahnung. –

+0

Das Problem ist, dass die Ausführung niemals 'Log.wtf (...)' für die letzte Datei erreicht, sie kommt irgendwie nie über 'closeEntry()' ... hinaus, so dass nur die Namen der ersten 11 Dateien ausgegeben werden. – BadCash

+1

Verwenden Sie einen Android [ZipInputStream] (https://developer.android.com/reference/java/util/zip/ZipInputStream.html)?Wahrscheinlich funktioniert [ZipArchiveInputStream] (https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.html) von Apache Commons in Ihrem Fall. –

Antwort

4

Nun, manchmal kann Ihr ZIP-Extraktionscode hängen bleiben, selbst wenn Sie alle vorherigen Ausgabe- und Eingabeströme schließen. Und ist dies a known bug: ZipInputStream#read 0.

Zusatz zurückkehren können:

Wenn Ihre ZIP-Datei einige Dateien mit Nicht-ASCII-Dateinamen enthält, werden Sie Problem konfrontiert mit extrahieren. Android ZipInputStream funktioniert nicht gut mit UTF-8, CP437 und so weiter.

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; 
}