咨询区

Dario

我需要在多台机器间同步大文件,不过文件高达 6G,通常我都是每几周手工同步一次,考虑到文件的文件名经常变,为了检验一致性,我考虑使用 ​​checksum​​ 机制。

我的计划是在 ​​源机器​​​ 和 ​​目标机器​​​ 上做 ​​校验和​​ ,然后在机器间copy文件的时候带上校验和,从而判断文件的完整性,我尝试用下面的代码做这件事情。

        static string GetChecksum(string file)
{
using (FileStream stream = File.OpenRead(file))
{
SHA256Managed sha = new SHA256Managed();

byte[] checksum = sha.ComputeHash(stream);

return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}

现在遇到的问题是:

  • SHA256 模式下,1.6G 文件需要耗费 20分钟算校验和。
  • MD5 模式下,1.6G 文件需要6.15分钟算校验和。

请问是否有更高效的方式来计算 校验和 呢?

回答区

Anton Gogolev

其实问题在于 ​​SHA256Managed​​ 一次只能读取 4096 byte,这对于 磁盘IO 的吞吐量来说实在太小了。

要想加速,可以用 BufferedStream 来包裹 FileStream,从而提高 FileStream 默认的 4096 的大小,不过这个值可以根据自己场景设置一个合理的范围,这里我设置成 ​​1M​​。

// Not sure if BufferedStream should be wrapped in using block
using(var stream = new BufferedStream(File.OpenRead(filePath), 1024 * 1024))
{
// The rest remains the same
}

在我的机器上。

  • SHA256 模式下,2G 文件需要 2分钟 算校验和。
  • MD5 模式下,2G 文件需要 1分钟 算校验和。

Fabske

你可以了解一下 ​​XxHash.Net​​, github地址:https:///wilhelmliao/xxHash.NET

而且 ​​xxHash​​ 算法看起来是最快的,下面是 xxHash 的 benchmark 图。

NET问答: C# 中是否有最高效的方式对大文件做 checksum ?_github

具体参考 github:https:///Cyan4973/xxHash

点评区

说起 ​​checksum​​​,让我想起来了​​计算机网络原理​​​,感觉是这门课中最多的一个词 😪😪😪,TCP,UDP 包无不有 checksum,它的作用大多还是怕在网络传输中由于干扰丢了一些字节,这样 checksum 就能精准的发现,不过我记得 redis 的 xxx.rdb 文件中也是有 ​​checksum​​ 的, 这玩意真的太重要了。