Я должен синхронизировать большие файлы через некоторые машины. Файлы могут составить до 6 ГБ в размере. Синхронизация будет сделана вручную каждые несколько недель. Я не могу принять имя файла во внимание, потому что они могут измениться в любое время.
Мой план состоит в том, чтобы создать контрольные суммы на целевом ПК и на источнике ПК и затем скопировать все файлы с контрольной суммой, которые уже не находятся в месте назначения месту назначения. Моя первая попытка была чем-то вроде этого:
using System.IO;
using System.Security.Cryptography;
private 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,6 ГБ-> 20 минут
- с MD5 с Файлом на 1,6 ГБ-> 6,15 минут
Существует ли лучшее - быстрее - способ получить контрольную сумму (возможно, с лучшей хеш-функцией)?
Если вам действительно нужно, чтобы это работало так, я бы сделал это (чтобы убедиться, что он работает с помощью клавиатуры и мыши)
// Not sure if BufferedStream should be wrapped in using block
using(var stream = new BufferedStream(File.OpenRead(filePath), 1200000))
{
// The rest remains the same
}
Не проверяйте контрольную сумму для всего файла, создавайте контрольные суммы каждые 100 МБ или около того, поэтому каждый файл имеет набор контрольных сумм.
Затем при сравнении контрольных сумм вы можете прекратить сравнение после первого другого контрольная сумма, раннее получение и избавление от обработки всего файла.
Это все равно займет полное время для идентичных файлов.
Вызов порта Windows md5sum.exe . Это примерно в два раза быстрее, чем реализация .NET (по крайней мере, на моем компьютере с файлом размером 1,2 ГБ)
public static string Md5SumByProcess(string file) {
var p = new Process ();
p.StartInfo.FileName = "md5sum.exe";
p.StartInfo.Arguments = file;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
p.WaitForExit();
string output = p.StandardOutput.ReadToEnd();
return output.Split(' ')[0].Substring(1).ToUpper ();
}
Вы делаете что-то неправильно (вероятно, слишком маленький буфер чтения). На машине невысокого возраста (Athlon 2x1800MP с 2002 года), на диске которой есть DMA, вероятно, неисправен (6,6 Мбит / с чертовски медленно при выполнении последовательных чтений):
Создайте файл размером 1 ГБ со «случайными» данными:
# dd if=/dev/sdb of=temp.dat bs=1M count=1024
1073741824 bytes (1.1 GB) copied, 161.698 s, 6.6 MB/s
# time sha1sum -b temp.dat
abb88a0081f5db999d0701de2117d2cb21d192a2 *temp.dat
1м5.
Ok - thanks to all of you - let me wrap this up: