我尝试使用逐字节比较,并比较计算的文件散列(下面的代码示例)。我有一个文件,复制它 - 比较两者 - 结果为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;
}
}
答案 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;
您忽略了b1
和b2
相互不平等和toRead
不相等的可能性。如果您只读取第一个流中的10个字节,而第二个流中的20个字节,当您要求30个字节时,该怎么办?您可能没有到达文件的末尾,但它仍然可能返回比您要求的数据更少的数据。 从不忽略Stream.Read
的返回值。 (您将其保存在变量中,然后忽略该变量。)
基本上你需要有独立的缓冲区,必要时补充这些缓冲区 - 跟踪你在每个缓冲区中的位置,以及有多少有用的数据。需要时,在每个缓冲区中读取更多数据。
然后就像Henk提到的那样,文件实际的其他问题只是通过打开来改变。