2008-09-30 8 views
0

Ich benutze SharpZipLib Version 0.85.5 um Dateien zu entpacken. Mein Code hat einige Monate lang gut funktioniert, bis ich eine ZIP-Datei fand, die es nicht mag.SharpZipLib - ZipException "Ende der zusätzlichen Daten" - Warum bekomme ich diese Ausnahme?

ICSharpCode.SharpZipLib.Zip.ZipException: End of extra data  
    at ICSharpCode.SharpZipLib.Zip.ZipExtraData.ReadCheck(Int32 length) in C:\C#\SharpZLib\Zip\ZipExtraData.cs:line 933  
    at ICSharpCode.SharpZipLib.Zip.ZipExtraData.Skip(Int32 amount) in C:\C#\SharpZLib\Zip\ZipExtraData.cs:line 921  
    at ICSharpCode.SharpZipLib.Zip.ZipEntry.ProcessExtraData(Boolean localHeader) in C:\C#\SharpZLib\Zip\ZipEntry.cs:line 925  
    at ICSharpCode.SharpZipLib.Zip.ZipInputStream.GetNextEntry() in C:\C#\SharpZLib\Zip\ZipInputStream.cs:line 269  
    at Constellation.Utils.Tools.UnzipFile(String sourcePath, String targetDirectory) in C:\C#\Constellation2\Utils\Tools.cs:line 90  
--- End of inner exception stack trace --- 

Hier ist meine unzip Methode:

 public static void UnzipFile(string sourcePath, string targetDirectory) 
    { 
     try 
     { 
      using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourcePath))) 
      { 
       ZipEntry theEntry; 
       while ((theEntry = s.GetNextEntry()) != null) 
       { 
        //string directoryName = Path.GetDirectoryName(theEntry.Name); 
        string fileName = Path.GetFileName(theEntry.Name); 

        if (targetDirectory.Length > 0) 
        { 
         Directory.CreateDirectory(targetDirectory); 
        } 

        if (fileName != String.Empty) 
        { 
         using (FileStream streamWriter = File.Create(targetDirectory + fileName)) 
         { 
          int size = 2048; 
          byte[] data = new byte[2048]; 
          while (true) 
          { 
           size = s.Read(data, 0, data.Length); 
           if (size > 0) 
           { 
            streamWriter.Write(data, 0, size); 
           } 
           else 
           { 
            break; 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new Exception("Error unzipping file \"" + sourcePath + "\"", ex); 
     } 
    } 

Die Datei unzips fein mit XP eingebauten ZIP-Unterstützung, WinZIP und 7-Zip. Die Ausnahme wird auf s.GetNextEntry() geworfen.

Antwort

1

Es ist möglich, dass die anderen ZIP-Tools zusätzliche Daten ignorieren, die beschädigt sind - oder es ist genauso möglich, dass es einen Fehler in #ZipLib gibt. (Ich fand vor einer Weile - eine bestimmte Datei, die nicht mit bestimmten Optionen komprimieren und dann sauber dekomprimieren würde.)

In diesem speziellen Fall, schlage ich vor, Sie auf der #ZipLib-Forum, um die Aufmerksamkeit der Entwickler zu bekommen . Wenn Ihre Datei keine sensiblen Daten enthält und Sie ein kurzes, aber vollständiges Programm erhalten können, wird dies sehr hilfreich sein.

0

Ich stimme Jon zu. Konnte nicht im Kommentar passt folgende:

(Obwohl dies Ihre Frage nicht beantwortet) Ist es nicht einfacher, etwas zu verwenden:

public static void UnzipFile(string sourcePath, string targetDirectory) 
{ 
    try 
    { 
     FastZip fastZip = new FastZip(); 
     fastZip.CreateEmptyDirectories = false; 
     fastZip.ExtractZip(sourcePath, targetDirectory,""); 
    } 
    catch(Exception ex) 
    { 
     throw new Exception("Error unzipping file \"" + sourcePath + "\"", ex); 
    } 
} 
0

die official ZIP specification See.

Jede Datei in einem ZIP-Archiv kann ein zusätzliches Feld enthalten. Ich denke, dass #ZipLib Ihnen sagt, dass die angegebene 'zusätzliche' Feldlänge länger war als die Menge an Daten, die zum Lesen verfügbar war; mit anderen Worten, die ZIP-Datei wurde höchstwahrscheinlich abgeschnitten.

0

Gemäss 4.5.3 von official ZIP specification, Felder Größe & CompressedSize von zusätzlichen Daten "MUSS nur erscheinen, wenn das entsprechende lokale oder zentrale Verzeichnis Datensatzfeld auf 0xFFFF oder 0xFFFFFFFF" gesetzt ist.

Aber SharpZipLib schreibt seine at-Methode ZipFile.WriteCentralDirectoryHeader nur, wenn "useZip64_ == UseZip64.On". Ich fügte hinzu entry.IsZip64Forced() Zustand und Fehler verschwinden)

  if (entry.CentralHeaderRequiresZip64) { 
      ed.StartNewEntry(); 

      if ((entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) || entry.IsZip64Forced()) 
      { 
       ed.AddLeLong(entry.Size); 
      } 

      if ((entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) || entry.IsZip64Forced()) 
      { 
       ed.AddLeLong(entry.CompressedSize); 
      }