.NET を使用して 2 つのファイルを高速に比較する方法は? 質問する

.NET を使用して 2 つのファイルを高速に比較する方法は? 質問する

典型的なアプローチFileStream 経由でバイナリを読み取り、バイトごとに比較することをお勧めします。

  • CRC などのチェックサム比較の方が高速でしょうか?
  • ファイルのチェックサムを生成できる .NET ライブラリはありますか?

ベストアンサー1

最も遅い方法は、2 つのファイルをバイトごとに比較することです。私が思いついた最も速い方法は、同様の比較ですが、一度に 1 バイトではなく、Int64 サイズのバイト配列を使用して、結果の数値を比較することです。

私が思いついたのは次の通りです:

    const int BYTES_TO_READ = sizeof(Int64);

    static bool FilesAreEqual(FileInfo first, FileInfo second)
    {
        if (first.Length != second.Length)
            return false;

        if (string.Equals(first.FullName, second.FullName, StringComparison.OrdinalIgnoreCase))
            return true;

        int iterations = (int)Math.Ceiling((double)first.Length / BYTES_TO_READ);

        using (FileStream fs1 = first.OpenRead())
        using (FileStream fs2 = second.OpenRead())
        {
            byte[] one = new byte[BYTES_TO_READ];
            byte[] two = new byte[BYTES_TO_READ];

            for (int i = 0; i < iterations; i++)
            {
                 fs1.Read(one, 0, BYTES_TO_READ);
                 fs2.Read(two, 0, BYTES_TO_READ);

                if (BitConverter.ToInt64(one,0) != BitConverter.ToInt64(two,0))
                    return false;
            }
        }

        return true;
    }

私のテストでは、この方法が単純な ReadByte() シナリオよりも 3 倍近く優れていることがわかりました。1000 回の実行を平均すると、この方法では 1063 ミリ秒、以下の方法 (単純なバイトごとの比較) では 3031 ミリ秒でした。ハッシュは常に 1 秒未満で、平均約 865 ミリ秒でした。このテストは、約 100 MB のビデオ ファイルで行いました。

比較のために使用した ReadByte とハッシュ メソッドを次に示します。

    static bool FilesAreEqual_OneByte(FileInfo first, FileInfo second)
    {
        if (first.Length != second.Length)
            return false;

        if (string.Equals(first.FullName, second.FullName, StringComparison.OrdinalIgnoreCase))
            return true;

        using (FileStream fs1 = first.OpenRead())
        using (FileStream fs2 = second.OpenRead())
        {
            for (int i = 0; i < first.Length; i++)
            {
                if (fs1.ReadByte() != fs2.ReadByte())
                    return false;
            }
        }

        return true;
    }

    static bool FilesAreEqual_Hash(FileInfo first, FileInfo second)
    {
        byte[] firstHash = MD5.Create().ComputeHash(first.OpenRead());
        byte[] secondHash = MD5.Create().ComputeHash(second.OpenRead());

        for (int i=0; i<firstHash.Length; i++)
        {
            if (firstHash[i] != secondHash[i])
                return false;
        }
        return true;
    }

おすすめ記事