14

ドライブ全体で特定のファイルを検索するプログラムに取り組んでいます。現時点では、既知のファイルの MD5 ハッシュを計算し、すべてのファイルを再帰的にスキャンして、一致するファイルを探しています。

唯一の問題は、大きなファイルでは MD5 が非常に遅いことです。誤検知の可能性を非常に低く保ちながら使用できる、より高速な代替手段はありますか?

すべてのコードは C# です。

ありがとうございました。

アップデート

MD5 でさえかなり高速であり、ディスク I/O が制限要因になるはずだと読みました。そのため、私のコードが最適ではない可能性があると私は信じています。このアプローチに問題はありますか?

        MD5 md5 = MD5.Create();
        StringBuilder sb = new StringBuilder();
        try
        {
            using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read))
            {
                foreach (byte b in md5.ComputeHash(fs))
                    sb.Append(b.ToString("X2"));
            }
            return sb.ToString();
        }
        catch (Exception)
        {
            return "";
        }
4

6 に答える 6

48

ファイル サイズが既に一致している場合にのみ、MD5 の一致を確認していることを願っています。

もう 1 つの最適化は、最初の 1K (またはその他の任意の、しかしかなり小さい数) の簡単なチェックサムを実行し、ファイル全体を処理する前にそれらが一致することを確認することです。

もちろん、これはすべて、特定のファイルの一致/不一致の決定を探しているだけであることを前提としています。

于 2008-11-13T23:32:47.447 に答える
10

暗号化要件に関係なく、ハッシュ衝突の可能性が存在するため、ハッシュ関数を使用して 2 つのファイルが同一であることを保証することはできません。

しばらく前に同様のコードを書きましたが、最初にすべてのファイルのインデックスを作成し、サイズが異なるものを破棄することで、かなり高速に実行できました。次に、残りのエントリに対して高速ハッシュ比較 (各ファイルの一部) が実行されました (このステップのバイト比較はあまり役に立たないことが判明しました。多くのファイル タイプには、ファイルの先頭に同一のバイトを持つ共通のヘッダーがあります)。この段階の後に残されたファイルは MD5 を使用してチェックされ、MD5 が一致した場合は最後にファイル全体のバイト比較が行われ、内容が同じであることを確認しました。

于 2010-07-22T22:58:08.577 に答える
6

ファイルを線形に読み取るだけですか?ファイル全体を読み取り、md5 ハッシュを計算してからハッシュを比較するのは、かなり無意味に思えます。

ファイルを一度に数バイトずつ順番に読み取ると、たとえば 4 バイトを読み取った後、大部分のファイルを破棄できます。そして、あなたのケースでは何も与えないハッシュ関数を計算するすべての処理オーバーヘッドを節約できます。

ドライブ内のすべてのファイルのハッシュが既にある場合は、それらを比較することは理にかなっていますが、それらをその場で計算する必要がある場合、ハッシュに利点はないようです.

ここで何か不足していますか?この場合、ハッシングは何をもたらしますか?

于 2008-11-13T23:31:04.687 に答える
6

最初に、実際のボトルネックは何かを考えてみましょう: ハッシュ関数自体ですか、それともディスク アクセス速度ですか? ディスクに制限されている場合、ハッシュ アルゴリズムを変更してもあまり効果がありません。あなたの説明から、一致を見つけるために常にディスク全体をスキャンしていることを意味します-最初にインデックスを構築し、次にインデックスに対して特定のハッシュのみを一致させることを検討してください。これははるかに高速です。

于 2008-11-13T23:32:22.860 に答える
5

MD5を使用してファイルを比較することには1つの小さな問題があります。それは、異なる同じMD5を持つ既知のファイルのペアが存在することです。

つまり、MD5を使用してファイルが異なるかどうかを判断できます(MD5が異なる場合、ファイルは異なる必要があります)が、MD5を使用してファイルが等しいかどうかを判断することはできませんファイルが等しい場合、MD5は同じですが、MD5が等しい場合、ファイルは等しい場合と等しくない場合があります)。

(SHA-1のように)まだ壊れていないハッシュ関数を使用するか、(@ SoapBoxが述べたように)より深い比較の候補を見つけるための高速な方法としてのみMD5を使用する必要があります。

参照:

于 2008-11-13T23:44:57.967 に答える
0

MD5CryptoServiceProvider と BufferedStream を使用する

        using (FileStream stream = File.OpenRead(filePath))
        {
            using (var bufferedStream = new BufferedStream(stream, 1024 * 32))
            {
                var sha = new MD5CryptoServiceProvider();
                byte[] checksum = sha.ComputeHash(bufferedStream);
                return BitConverter.ToString(checksum).Replace("-", String.Empty);
            }
        }
于 2013-07-19T10:30:22.777 に答える