コンテンツ全体を読み取る必要なしに(検証目的で)2つのファイルを比較できる高速アルゴリズムはありますか?
5 に答える
両方のファイルでMD5ハッシュを使用して、そのように比較することができます。ただし、技術的にはファイル全体を読み取ります。私が思わないことを確認せずに100%の確実性を持つことはできません。
C#では、次の方法でこれを行います(申し訳ありませんが、特定の言語については言及していません)。
protected string GetMD5HashFromFile(string fileName)
{
byte[] retVal = { };
using (FileStream file = new FileStream(fileName, FileMode.Open))
using (MD5 md5 = new MD5CryptoServiceProvider())
{
retVal = md5.ComputeHash(file);
}
if (retVal.Length > 0)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
else
{
return string.Empty;
}
}
bool CompareFiles(string fileName1, string fileName2)
{
return (GetMD5HashFromFile(fileName1) == GetMD5HashFromFile(fileName2));
}
同じサイズの2つのファイルが両方を完全に読み取らなければ等しいと判断することは数学的に不可能ですが、両方を完全に読み取らなければ等しくないと判断することは非常に可能です。これは、ハッシュ関数や短絡比較など、さまざまな方法で実行できます。
ファイルのビットを読み取るカスタムCRCプロシージャを作成できます。たとえば、ファイル全体をCRCする代わりに、1kごとに16バイトなど。もちろん、データはあなたが見ていない場所で変更され、比較されたブロックに影響を与えない可能性があるため、よりリスクが高くなります。ただし、2つの非常に異なるデータセットが同じ値を返す可能性があるため、CRCも少し危険です。
すべてのバイトを読み取らない限り、ファイルが同じであることを100%確認するアルゴリズムはありません。証明は簡単です-そのようなアルゴリズムが存在すると仮定し、それを使用して2つのファイルを比較します。これは、アルゴリズムによって一部のバイトが読み取られないことを意味します。一方のファイルでこれらのバイトを変更することでアルゴリズムを失敗させることができますが、もう一方のファイルでは失敗させることはできません。
両方のファイルを完全に読み取って、それらが等しいことを完全に確認することは避けられないのではないかと思います。
最初に両方のファイルのサイズを確認できます。それらが異なる場合、ファイルは異なります(ただし、行区切り文字でのみ異なるテキストファイルについてはどうでしょうか?)。
サイズが同じである場合、先に進む正しい方法はわかりませんが、両方のファイルの読み取りを開始します。もちろん、バッファが異なるとすぐに停止することもできますが、最後の文字が処理されたときにファイルが実際に等しいとしか言えません。