Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#/.NET中同步两个目录(从源目录更新目标目录)_C#_.net - Fatal编程技术网

在C#/.NET中同步两个目录(从源目录更新目标目录)

在C#/.NET中同步两个目录(从源目录更新目标目录),c#,.net,C#,.net,我想同步两个目录,这样在操作之后,目标目录就是源目录的精确副本。将新的源文件/子目录添加到目标中,较新的源文件将替换较旧的目标版本,源中缺少的文件将从目标中删除 我知道我可以递归地遍历这两棵树,检查是否存在,并比较上次写入日期 我的问题:是否有现成的东西可以用来代替编写自己的代码?类似于TargetDir.UpdateFromSourceDir(SourceDir)的东西:-) 我在这里找到了带有DirectorySynchronization类的System.DirectoryServices

我想同步两个目录,这样在操作之后,目标目录就是源目录的精确副本。将新的源文件/子目录添加到目标中,较新的源文件将替换较旧的目标版本,源中缺少的文件将从目标中删除

我知道我可以递归地遍历这两棵树,检查是否存在,并比较上次写入日期

我的问题:是否有现成的东西可以用来代替编写自己的代码?类似于
TargetDir.UpdateFromSourceDir(SourceDir)的东西:-)


我在这里找到了带有DirectorySynchronization类的System.DirectoryServices:。从它的名字来看,它似乎可以做我想做的事情,但从它的方法来看,我对此表示怀疑。

在我将展示的示例中,有很多方法可以做到这一点

  • 最简单的方法是使用同步库
  • 否则,将删除并复制目录
  • 如果您不想这样做,最安全的方法(尽管容易发生更多的数据竞争)是散列所有文件,列出要删除、添加和更新的文件列表
  • 最不安全的方法是执行上述操作,但使用文件日期
就个人而言,我只是删除和复制,然后转到其他内容,不过你可以试试这个

预警:如果可以找到同步库,请使用同步库。这纯粹是出于学术目的,并不等同于世界上最好的解决方案

给定的

public static (HashSet<string> dirs, HashSet<(string file,long tick)> files) Get(string dir)
{

   string CleanPath(string path) => path.Substring(dir.Length).TrimStart('/', '\\');

   // replace this with a hashing method if you need
   long GetUnique(string path) => new FileInfo(path).LastWriteTime.Ticks;

   var directories = Directory.GetDirectories(dir, "*.*", SearchOption.AllDirectories);

   var dirHash = directories.Select(CleanPath).ToHashSet();

   // this could be paralleled if need be (if using a hash) 
   var fileHash = directories.SelectMany(Directory.EnumerateFiles)
      .Select(file => (name: CleanPath(file), ticks : GetUnique(file)))
      .ToHashSet();

   return (dirHash, fileHash);    
}

注意:失败的方法有很多,假设您有权限这样做,并且文件没有被锁定。这还应该有大量的错误检查,可能需要定制,并且在使用它之前,您应该进行大量的尽职调查(请注意)

建议使用Microsoft Sync Framework。我通过NuGet获得了Microsoft.SyncFramework的
。我认为这意味着这个库基于另一个不再存在的库

由于我的程序只能在Windows下运行,我在这里找到了一个简单的解决方案:。其想法是运行Windows附带的命令行工具robocopy.exe,并完全执行我想要的操作(使用选项/MIR)


这回答了你的问题吗@查理脸:谢谢。这个看起来不错,不过我不知道怎么用。他们提到了FileSyncProvider和SyncOrchestrator,但没有说明要包括哪些程序集以及需要使用什么using指令。“你能解释一下吗?”汉斯·帕桑:谢谢。这似乎只是用蛮力(不检查目标文件是否为当前文件)覆盖所有源文件的所有目标文件,我不认为当源文件中不再存在文件时会从目标文件中删除这些文件。要做到这一点,最简单的方法是删除并复制目录。如果您不想这样做,最安全的方法(尽管容易发生更多的数据竞争)是散列所有文件,列出要删除、添加和更新的文件列表。最不安全的方法是执行上述操作,但使用上次修改的日期和时间。就我个人而言,我只是删除和复制,并转移到其他东西上,谢谢你为此付出了这么多的努力。我找不到同步库。我想推荐的Microsoft库已经不存在了。我喜欢你的方法,从中我学到了很多。非常感谢。
var result1 = Get(dir1);
var result2 = Get(dir2);

var dirsToRemove = result2.dirs.Where(x => !result1.dirs.Contains(x));
var filesToRemove = result2.files.Where(x => !result1.files.Contains(x));
var filesToAdd = result1.files.Where(x => !result2.files.Contains(x));

foreach (var fileToRemove in filesToRemove)
   Console.WriteLine("Deleting : " + Path.Combine(dir2, fileToRemove.file));

foreach (var dirToRemove in dirsToRemove)
   Console.WriteLine("Deleting : " + Path.Combine(dir2, dirToRemove));

foreach (var fileToAdd in filesToAdd)
   Console.WriteLine("Adding : " + Path.Combine(dir2,fileToAdd.file));
using (Process RoboCopyProcess = new Process())
{
  RoboCopyProcess.StartInfo.FileName = "robocopy.exe";
  RoboCopyProcess.StartInfo.Arguments = SourceDirPath + " " + TargetDirPath + " /MIR";
  RoboCopyProcess.StartInfo.UseShellExecute = false;
  RoboCopyProcess.StartInfo.CreateNoWindow = true;
  RoboCopyProcess.Start();
  RoboCopyProcess.WaitForExit();
}