我知道使用人们已经发明的校验和算法总是更好。我想通过执行校验和来比较两个文件是否相同。这些文件通过网络位于两台不同的计算机上,因为它们通过网络执行校验和,而不是在处理像我这样的大文件时复制整个文件。 (我将首先执行其他测试,例如确保文件的长度等等。)
所以我创建了这个简单的算法:
private static double GetChecksum2(string file)
{
double checkSum = 0;
var stream = File.OpenRead(file);
// the bigger the chunck size the faster but the more memory usage by cpu
// also when sending file over network it should not be that much more efficient
int chunckSize = (int) Math.Pow(2,20); // 10 => kilobite 20 => megabite 30 => gigabite etc..
byte[] buffer = new byte[chunckSize];
int bytesRead = 0;
while ( // while bytesRead > 0
(bytesRead =
(stream.Read(buffer, 0, buffer.Length)) // returns the number of bytes read or 0 if no bytes read
) > 0)
{
//buffer is now an array of size bytesRead
// write those bytes to a file, perform checksum of file
// etc...
// temp check sum use a better algorithm I dont know if other computers will round
// doubles diferently
for (int i = 0; i < bytesRead; i++)
{
checkSum = (((buffer[i] + i)/2 + checkSum))*.45;
}
//SHA256Managed sha = new SHA256Managed();
//byte[] checksum = sha.ComputeHash(buffer);
}
return checkSum;
}
我不知道使用此算法实现两个不同文件的校验和的概率是多少。
执行1.06 GB文件的校验和时,需要5.2秒才能完成,校验和为321840.207306214
当我使用SHA256Managed()算法时,需要35.8秒。
我知道两个文件具有相同校验和的可能性与这个算法不同,远低于我的算法。但是使用我的算法要快得多,我认为赔率也应该很低......
或许我应该使用更快的算法,我不知道它已经存在......
实现此算法是否安全。我需要通过我的网络进行大量的文件传输,如果我可以使用校验和算法来比较文件,这将是很好的。也许我可以在chuncks中拆分每个文件,只需替换校验和不匹配的块!
答案 0 :(得分:3)
浮点数学是非确定性的。您可能会在不同的计算机或.net版本上获得略有不同的结果。在您的算法中,可以通过epsilon比较来避免,但在许多算法中,它根本无法避免。
您的算法的另一个问题是早期字节的贡献变得指数级小。即只有文件的最后部分影响哈希。快速估计只考虑最后几个kB。这意味着你的哈希不适合它的目的。
如果我们忽略舍入误差,我们可以简化您的公式:
(((buffer[i] + i)/2 + checkSum))*.45
buffer[i]*0.45/2 + i*0.45/2 + checkSum*0.45
求解递归给了我们:
Sum(buffer[i]/2*(0.45^(length-1)) + i*(0.45^(length-1)))
第二个术语只取决于长度,所以在比较长度相等的文件时,你会留下:
Sum(buffer[i]/2*(0.45^(length-1)))
答案 1 :(得分:1)
使用double
作为校验和容易出现浮点问题。我认为这是一个非常糟糕的主意。我也认为重新发明轮子也是一个糟糕的决定。有many checksum algorithms可供您重复使用。
此外,还有一些相关的问题: