2012-08-16 14 views
10

私は現在、SharpZip APIを使用してZIPファイルエントリを処理しています。それはジッパーと解凍のために素晴らしい作品です。しかし、ファイルがジップであるかどうかを特定するのは難しいです。ファイルストリームを解凍できるかどうかを検出する方法があるかどうかを知る必要があります。もともと私は使用しましたC#.zipファイルを識別する

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) 
{ 

LZipStreamTesterは毎回nullになり、if文は失敗します。私はそれを/バッファなしで試しました。なぜ誰にでも洞察力を与えることができますか?私はファイル拡張子を確認できることを知っています。私はそれよりも決定的なものが必要です。私は、zipには魔法の#があることも知っていますが、それはフォーマットの要件ではないため、常にそこに存在するという保証はありません。

も、私は私のプロジェクトではなくsharpzipのものに移行するかもしれませんが、私はまだここCanDecompressEntryと同様の方法/ PARAM表示されませんでした必要なので、4.5がネイティブのzipサポートを持つ.NETについて読む:http://msdn.microsoft.com/en-us/library/3z72378a%28v=vs.110%29

私の最後の手段try catchを使用してファイルを解凍しようとします。

+0

私の質問の最も単純な形式は、これは「上記のコードでは、なぜif文がfalseを返すのですか?」 –

答えて

5

これは、非圧縮、PKZIP圧縮(sharpziplib)または圧縮されたGzip(.net)で圧縮されたデータを処理する必要があるコンポーネントの基本クラスです。おそらくあなたよりも少しは必要ですが、あなたに行くべきです。これは、@ PhonicUKの提案を使用してデータストリームのヘッダーを解析する例です。小さな工場で見られる派生クラスは、PKZipとGZipの解凍の詳細を処理しました。

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

これは参考になりますが、PKファイルのヘッダーやマジックナンバーは、ファイルがzipかどうかを判断する信頼できる方法ではありません。ありがとう、結構です。 –

+1

これに問題はありませんでしたが、これは圧縮されたデータのソースがよく理解され、制御されているシステムからのものです。がんばろう! – dkackman

+0

ファイルシステムの監査を行う必要があります。私はPKの魔法の数のチェック、ファイルの拡張子の組み合わせ、および解凍をキャッチしようとすると十分だと思います。もともとは、ファイルがZIPであるかどうかを判断するためにtry catchを使用しないようにしたいのですが、そこにある必要がありました。マジックナンバーのジップを仮定したとしても、ジップが破損しているかどうかを判断するためにキャッチを試す必要があります。私はあなたのことを言いたいのですが、今はあまりにも冗談です。あいまいさを取り除くためにファイルをアップロードする方法を改訂しました。再度、感謝します。 –

7

あなたがいずれかを実行できます。

  • は、zipファイル
であるかどうかを確認するために、ファイルのヘッダをパースのtry-catch構造を使用して
  • 潜在的なzipファイルの構造を読み取ろう

    ZIPファイルは常に最初の4バイトとして0x04034b50で始まります(http://en.wikipedia.org/wiki/Zip_(file_format)#File_headers

  • +0

    Wikipediaや他の情報源によれば、マジックナンバーは、ファイルがzipファイルであるかどうかを判断する良い方法ではないことが記載されています。 また、キャッチしようとするのを避けたいのですが、それが現在の方法です。 –

    +1

    注:0x04034B50はリトルエンディアンであるため、ファイルの最初のバイトは0x50であり、2番目のバイトは0x4Bです。 – vojta

    2

    Web用にプログラミングする場合は、ファイルの内容タイプを確認してください。application/z ip

    9

    ビューhttps://stackoverflow.com/a/16587134/206730参照

    チェック以下のリンク:

    icsharpcode-sharpziplib-validate-zip-file

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

    ZIPファイルは常に0x04034b50(4バイト)で始まる
    もっと見る:http://en.wikipedia.org/wiki/Zip_(file_format)#File_headers

    使用例:

     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; 
          } 
         } 
    
        } 
    
    関連する問題