web-dev-qa-db-ja.com

C#で2つのファイルを比較する

C#で2つのファイルを比較して、それらが異なるかどうかを確認したいと思います。それらは同じファイル名を持ち、異なる場合は正確に同じサイズです。手動でファイルを読み取らずにこれを行う高速な方法があるかどうかだけを考えていました。

ありがとう

15
Toz

どれだけ遠くまで見たいかによって、 Diff.NET を見ることができます。

次に、単純なファイル比較関数を示します。

// This method accepts two strings the represent two files to 
// compare. A return value of 0 indicates that the contents of the files
// are the same. A return value of any other value indicates that the 
// files are not the same.
private bool FileCompare(string file1, string file2)
{
     int file1byte;
     int file2byte;
     FileStream fs1;
     FileStream fs2;

     // Determine if the same file was referenced two times.
     if (file1 == file2)
     {
          // Return true to indicate that the files are the same.
          return true;
     }

     // Open the two files.
     fs1 = new FileStream(file1, FileMode.Open, FileAccess.Read);
     fs2 = new FileStream(file2, FileMode.Open, FileAccess.Read);

     // Check the file sizes. If they are not the same, the files 
        // are not the same.
     if (fs1.Length != fs2.Length)
     {
          // Close the file
          fs1.Close();
          fs2.Close();

          // Return false to indicate files are different
          return false;
     }

     // Read and compare a byte from each file until either a
     // non-matching set of bytes is found or until the end of
     // file1 is reached.
     do 
     {
          // Read one byte from each file.
          file1byte = fs1.ReadByte();
          file2byte = fs2.ReadByte();
     }
     while ((file1byte == file2byte) && (file1byte != -1));

     // Close the files.
     fs1.Close();
     fs2.Close();

     // Return the success of the comparison. "file1byte" is 
     // equal to "file2byte" at this point only if the files are 
     // the same.
     return ((file1byte - file2byte) == 0);
}
28
James Johnson

手動でファイルを読み取らずにこれを行う高速な方法があるかどうかだけを考えていました。

あんまり。

Ifファイルにハッシュが付属している場合は、ハッシュを比較できます。ハッシュが異なる場合は、ファイルが異なると結論付けることができます(ただし、同じハッシュは、ファイルが同じであるという意味ではなく、それでもバイトごとの比較を行う必要があります)。

ただし、ハッシュはファイル内のすべてのバイトを使用するため、いずれにしても、ある時点でファイルをバイト単位で読み取る必要があります。そして実際には、バイトごとの単純な比較は、ハッシュを計算するよりも高速です。これは、ハッシュはバイトごとの比較と同じようにすべてのバイトを読み取りますが、ハッシュは時間を追加する他のいくつかの計算を行うためです。さらに、バイトごとの比較は、等しくないバイトの最初のペアで早期に終了する可能性があります。

最後に、バイト単位の読み取りの必要性を回避することはできません。ハッシュが等しい場合でも、ファイルが等しいとは限りません。この場合でも、バイト単位で比較する必要があります。

18
jason

ファイルにタイムスタンプを書き込むことができるかどうかはわかりません。そうでない場合、独自の代替手段は、ファイルの内容を比較することです。

単純なアプローチは、ファイルをバイト単位で比較することですが、ファイルを他のファイルと数回比較する場合は、ファイルのハッシュコードを計算して比較できます。

次のコードスニペットは、その方法を示しています。

    public static string CalcHashCode(string filename)
    {
        FileStream stream = new FileStream(
            filename,
            System.IO.FileMode.Open,
            System.IO.FileAccess.Read,
            System.IO.FileShare.ReadWrite);

        try
        {
            return CalcHashCode(stream);
        }
        finally
        {
            stream.Close();
        }
    }

    public static string CalcHashCode(FileStream file)
    {
        MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
        Byte[] hash = md5Provider.ComputeHash(file);
        return Convert.ToBase64String(hash);
    }

ファイルを他のファイルと一度以上比較する場合は、ファイルハッシュを保存して比較できます。単一の比較では、バイト間の比較の方が優れています。また、ファイルが変更された場合はハッシュを再計算する必要がありますが、大規模な比較(複数回)を行う場合は、ハッシュアプ​​ローチを使用することをお勧めします。

4
Daniel Peñalba

ファイル名が同じで、ファイルサイズが同じである場合、いいえ、コンテンツを調べずにそれらのコンテンツが異なるかどうかを確認する方法はありません。

3
AllenG

ファイルをストリームに読み込んでから、ストリームをハッシュします。それはあなたに比較のための信頼できる結果を与えるはずです。

byte[] fileHash1, fileHash2;

using (SHA256Managed sha = new SHA256Managed())
{
    fileHash1 = sha.ComputeHash(streamforfile1);
    fileHash2 = sha.ComputeHash(streamforfile2);
}

for (int i = 0; (i < fileHash1.Length) && (i < fileHash2.Length); i++)
    {
        if (fileHash[i] != fileHash2[i]) 
        { 
             //files are not the same
             break; 
        }
    }
0
Random