2012-08-16 4 views
10

Ich verwende derzeit die SharpZip API, um meine ZIP-Dateieinträge zu bearbeiten. Es funktioniert wunderbar zum Zippen und Entpacken. Obwohl ich Probleme habe festzustellen, ob eine Datei eine Zip ist oder nicht. Ich muss wissen, ob es einen Weg gibt zu erkennen, ob ein Dateistrom dekomprimiert werden kann. Ursprünglich verwendete ichC# .net ZIP-Datei identifizieren

FileStream lFileStreamIn = File.OpenRead(mSourceFile); 
lZipFile = new ZipFile(lFileStreamIn); 
ZipInputStream lZipStreamTester = new ZipInputStream(lFileStreamIn, mBufferSize);// not working 
lZipStreamTester.Read(lBuffer, 0, 0); 
if (lZipStreamTester.CanDecompressEntry) 
{ 

Der LZipStreamTester wird jedes Mal null und die If-Anweisung schlägt fehl. Ich habe es mit/ohne Puffer versucht. Kann jemand irgendeinen Einblick geben, warum? Ich bin mir bewusst, dass ich nach Dateierweiterung suchen kann. Ich brauche etwas, das definitiver ist. Ich bin mir auch bewusst, dass Zip eine magische # (PK etwas) hat, aber es ist keine Garantie, dass es immer da sein wird, weil es keine Anforderung des Formats ist.

Auch lese ich über .net 4.5 mit nativem zip Unterstützung so mein Projekt, dass anstelle von sharpzip wandern kann, aber ich brauche noch nicht hier gesehen habe, ein Verfahren/param ähnlich wie CanDecompressEntry: http://msdn.microsoft.com/en-us/library/3z72378a%28v=vs.110%29

Meinen letzten Ausweg wird es sein, einen try-catch zu verwenden und ein entpacken der Datei zu versuchen.

+0

Die einfachste Form meiner Frage ist "In dem obigen Code, warum tut die if-Anweisung false zurück?" –

Antwort

5

Dies ist eine Basisklasse für eine Komponente, die Daten verarbeiten muss, die entweder unkomprimiert, PKZIP-komprimiert (shartziplib) oder GZip-komprimiert (integriert in .net) sind. Vielleicht ein bisschen mehr als du brauchst, aber sollte dich in Gang bringen. Dies ist ein Beispiel für den Vorschlag von @ PhonicUK, den Header des Datenstroms zu analysieren. Die abgeleiteten Klassen, die Sie in der kleinen Fabrik Mathod sehen, behandelt die Besonderheiten der PKZip und GZip Dekompression.

abstract class Expander 
{ 
    private const int ZIP_LEAD_BYTES = 0x04034b50; 
    private const ushort GZIP_LEAD_BYTES = 0x8b1f; 

    public abstract MemoryStream Expand(Stream stream); 

    internal static bool IsPkZipCompressedData(byte[] data) 
    { 
     Debug.Assert(data != null && data.Length >= 4); 
     // if the first 4 bytes of the array are the ZIP signature then it is compressed data 
     return (BitConverter.ToInt32(data, 0) == ZIP_LEAD_BYTES); 
    } 

    internal static bool IsGZipCompressedData(byte[] data) 
    { 
     Debug.Assert(data != null && data.Length >= 2); 
     // if the first 2 bytes of the array are theG ZIP signature then it is compressed data; 
     return (BitConverter.ToUInt16(data, 0) == GZIP_LEAD_BYTES); 
    } 

    public static bool IsCompressedData(byte[] data) 
    { 
     return IsPkZipCompressedData(data) || IsGZipCompressedData(data); 
    } 

    public static Expander GetExpander(Stream stream) 
    { 
     Debug.Assert(stream != null); 
     Debug.Assert(stream.CanSeek); 
     stream.Seek(0, 0); 

     try 
     { 
      byte[] bytes = new byte[4]; 

      stream.Read(bytes, 0, 4); 

      if (IsGZipCompressedData(bytes)) 
       return new GZipExpander(); 

      if (IsPkZipCompressedData(bytes)) 
       return new ZipExpander(); 

      return new NullExpander(); 
     } 
     finally 
     { 
      stream.Seek(0, 0); // set the stream back to the begining 
     } 
    } 
} 
+0

Dies ist hilfreich, aber von den Recherchen, die ich gemacht habe, ist der PK-Dateikopf oder die magische Zahl keine zuverlässige Methode, um festzustellen, ob eine Datei zip ist. Trotzdem danke. –

+1

Hatte keine Probleme damit, aber dies ist von einem System, wo die Quellen der komprimierten Daten gut verstanden und kontrolliert werden. Viel Glück! – dkackman

+0

Um sicher zu gehen, muss ich ein Audit in unserem Dateisystem durchführen. Ich glaube, dass die Mischung aus einer PK-Nummer, einer Dateierweiterung und einem Versuch zum Aufdecken ausreicht. Wir wollten ursprünglich vermeiden, einen try catch zu verwenden, um festzustellen, ob es sich bei der Datei um eine zip-Datei handelt, aber sie muss darin enthalten sein. Selbst wenn wir eine Zip-on-Magic-Nummer annehmen, müssen wir noch versuchen, catch zu finden, um festzustellen, ob die Zip-Datei beschädigt ist. Ich wünschte, ich könnte dich repäsentieren, aber jetzt zu noob. Wir haben auch überarbeitet, wie wir Dateien hochladen werden, um etwas von der Mehrdeutigkeit zu entfernen. Danke noch einmal. –

7

können Sie entweder:

  • einen Try-Catch-Struktur verwenden und versuchen, die Struktur eines potenziellen Zip-Datei-Header
  • Parse die Datei zu lesen, um zu sehen, ob es sich um eine Zip-Datei ist

ZIP-Dateien immer mit 0x04034b50 als ersten 4 Bytes (http://en.wikipedia.org/wiki/Zip_(file_format)#File_headers) starten

+0

Wikipedia und andere Quellen haben aufgelistet, dass die magische Zahl keine gute Möglichkeit ist festzustellen, ob es sich bei einer Datei um eine Zip-Datei handelt, da sie für das Dateiformat einer Zip-Datei nicht erforderlich ist. Alternativ möchten wir vermeiden versuchen versuchen, aber das ist die aktuelle Methode. –

+1

Hinweis: 0x04034B50 ist Little Endian, also das erste Byte der Datei ist 0x50, das zweite Byte ist 0x4B und so weiter ... – vojta

2

Wenn Sie für Web programmieren, können Sie die Datei Inhalt Typ überprüfen: application/z ip

9

Ansicht https://stackoverflow.com/a/16587134/206730 Referenz

Überprüfen Sie die unten stehenden Links:

icsharpcode-sharpziplib-validate-zip-file

How-to-check-if-a-file-is-compressed-in-c#

ZIP-Dateien immer mit 0x04034b50 (4 Byte) starten
Mehr: http://en.wikipedia.org/wiki/Zip_(file_format)#File_headers

Verwendungsbeispiel:

 bool isPKZip = IOHelper.CheckSignature(pkg, 4, IOHelper.SignatureZip); 
     Assert.IsTrue(isPKZip, "Not ZIP the package : " + pkg); 

// http://blog.somecreativity.com/2008/04/08/how-to-check-if-a-file-is-compressed-in-c/ 
    public static partial class IOHelper 
    { 
     public const string SignatureGzip = "1F-8B-08"; 
     public const string SignatureZip = "50-4B-03-04"; 

     public static bool CheckSignature(string filepath, int signatureSize, string expectedSignature) 
     { 
      if (String.IsNullOrEmpty(filepath)) throw new ArgumentException("Must specify a filepath"); 
      if (String.IsNullOrEmpty(expectedSignature)) throw new ArgumentException("Must specify a value for the expected file signature"); 
      using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
      { 
       if (fs.Length < signatureSize) 
        return false; 
       byte[] signature = new byte[signatureSize]; 
       int bytesRequired = signatureSize; 
       int index = 0; 
       while (bytesRequired > 0) 
       { 
        int bytesRead = fs.Read(signature, index, bytesRequired); 
        bytesRequired -= bytesRead; 
        index += bytesRead; 
       } 
       string actualSignature = BitConverter.ToString(signature); 
       if (actualSignature == expectedSignature) return true; 
       return false; 
      } 
     } 

    }