比较2个文件的问题 - 假的时候应该是真的吗?

时间:2011-03-09 09:55:11

标签: c# .net compare

我尝试使用逐字节比较,并比较计算的文件散列(下面的代码示例)。我有一个文件,复制它 - 比较两者 - 结果为TRUE。但是当我打开其中一个文件时问题就出现了:

使用MS word文件 - 打开和关闭其中一个文件后,结果仍为TRUE,但是,例如,当我删除文件中的最后一个符号时,再将其写回,然后再次尝试比较 - 结果为FALSE。文件基本相同,从理论上讲,似乎在逐字节中它们不再相同。

使用Excel文件 - 即使打开文件也会导致函数返回false。它应该真的像那样吗?我能想到的唯一改变的是上次访问时间。但是在逐字节比较时是否需要考虑?

所以我想问一下,这种比较真的应该像这样工作吗?我能做些什么来逃避这个吗?在我的程序中,我将比较most.pdf文件,其中编辑不是一个选项,但我仍然想知道为什么它会像这样。

Byte-Byte with buffer:

static bool FilesAreEqualFaster(string f1, string f2)
    {
        // get file length and make sure lengths are identical
        long length = new FileInfo(f1).Length;
        if (length != new FileInfo(f2).Length)
            return false;

        byte[] buf1 = new byte[4096];
        byte[] buf2 = new byte[4096];

        // open both for reading
        using (FileStream stream1 = File.OpenRead(f1))
        using (FileStream stream2 = File.OpenRead(f2))
        {
            // compare content for equality
            int b1, b2;
            while (length > 0)
            {
                // figure out how much to read
                int toRead = buf1.Length;
                if (toRead > length)
                    toRead = (int)length;
                length -= toRead;

                // read a chunk from each and compare
                b1 = stream1.Read(buf1, 0, toRead);
                b2 = stream2.Read(buf2, 0, toRead);
                for (int i = 0; i < toRead; ++i)
                    if (buf1[i] != buf2[i])
                        return false;
            }
        }

        return true;
    }

哈希:

private static bool CompareFileHashes(string fileName1, string fileName2)
    {
        // Compare file sizes before continuing.
        // If sizes are equal then compare bytes.
        if (CompareFileSizes(fileName1, fileName2))
        {
            // Create an instance of System.Security.Cryptography.HashAlgorithm
            HashAlgorithm hash = HashAlgorithm.Create();

            // Declare byte arrays to store our file hashes
            byte[] fileHash1;
            byte[] fileHash2;

            // Open a System.IO.FileStream for each file.
            // Note: With the 'using' keyword the streams
            // are closed automatically.
            using (FileStream fileStream1 = new FileStream(fileName1, FileMode.Open),
                              fileStream2 = new FileStream(fileName2, FileMode.Open))
            {
                // Compute file hashes
                fileHash1 = hash.ComputeHash(fileStream1);
                fileHash2 = hash.ComputeHash(fileStream2);
            }

            return BitConverter.ToString(fileHash1) == BitConverter.ToString(fileHash2);
        }
        else
        {
            return false;
        }
    }

1 个答案:

答案 0 :(得分:2)

除此之外,这段代码错了:

b1 = stream1.Read(buf1, 0, toRead);
b2 = stream2.Read(buf2, 0, toRead);
for (int i = 0; i < toRead; ++i)
    if (buf1[i] != buf2[i])
        return false;

您忽略了b1b2相互不平等和toRead不相等的可能性。如果您只读取第一个流中的10个字节,而第二个流中的20个字节,当您要求30个字节时,该怎么办?您可能没有到达文件的末尾,但它仍然可能返回比您要求的数据更少的数据。 从不忽略Stream.Read的返回值。 (您将其保存在变量中,然后忽略该变量。)

基本上你需要有独立的缓冲区,必要时补充这些缓冲区 - 跟踪你在每个缓冲区中的位置,以及有多少有用的数据。需要时,在每个缓冲区中读取更多数据。

然后就像Henk提到的那样,文件实际其他问题只是通过打开来改变。