我需要覆盖从源到目标目录的文件。 每个文件夹的结构都不同,所以我试图以通用的方式进行。 问题是,每个文件夹(源和目标)可能有许多子目录或根本没有。
我目前的代码是:
//copy and overwrite the files depending on whatever is in the destination
//search through the destination to find the file
foreach (var dstfile in Directory.GetFiles(targetDir))
{
//search through the source to find the matching file
foreach (var srcfile in Directory.GetFiles(sourceDir))
{
//cut off the source file from the source path
strSrcFile = srcfile.Split(Path.DirectorySeparatorChar).Last();
strDstFile = dstfile.Split(Path.DirectorySeparatorChar).Last();
//if the destination and source files match up, replace the desination with the source
if (strSrcFile == strDstFile)
{
File.Copy(srcfile, Path.Combine(targetDir, Path.GetFileName(strSrcFile)), true);
}
}
}
//look through the subfolders to see if any files match up
foreach (var srcFolder in Directory.GetDirectories(sourceDir))
{
//search through the source for the files
foreach (var srcFile in Directory.GetFiles(srcFolder))
{
//search through the destination for the files
foreach (var dstFile in Directory.GetFiles(targetDir))
{
正如你所看到的,有许多foreach循环,有没有办法简化这个?
答案 0 :(得分:1)
我没有对此进行测试,但这应该有效(不是100%效率),至少应该给你一些指示
public void UpdateFiles(string directory, string otherDir)
{
var dirFiles = Directory.EnumerateFiles(directory, "*",
SearchOption.AllDirectories);
var otherDirFiles = Directory.EnumerateFiles(otherDir, "*",
SearchOption.AllDirectories);
foreach (var file in dirFiles)
{
string fi = Path.GetFileName(file);
var newFile = otherDirFiles.Where(x => fi == Path.GetFileName(x));
foreach(var foundFile in newFile)
File.Copy(file , foundFile, true);
}
}
答案 1 :(得分:1)
创建目标目录的哈希(字典),然后遍历源目录并查看文件是否已存在。
Dictionary<string,string> lut1 = new Dictionary<string,string>();
foreach (var dstfile in Directory.GetFiles(targetDir))
{
strDstFile = dstfile.Split(Path.DirectorySeparatorChar).Last();
lut1 [strDstFile ] = dstfile;
}
foreach (var srcfile in Directory.GetFiles(sourceDir))
{
strSrcFile = srcfile.Split(Path.DirectorySeparatorChar).Last();
string dstfile;
if (lut1.TryGetValue(strSrcFile, out dstfile)) {
File.Copy( srcfile,dstfile,true);
}
}
答案 2 :(得分:1)
我只是在控制台应用程序中这样做了...测试它是为主目标文件夹和子文件夹工作,虽然可能不是最有效的。
请致电:
OperateOnSourceFiles(sourceDir, targetDir);
将检查源中的当前文件,然后递归查看所有源子目录。
private static void OperateOnSourceFiles(string source, string targetDir)
{
//Processes current source folder files
foreach (var file in Directory.GetFiles(source))
{
OverWrite(targetDir, file);
}
//Recursively processes files in source subfolders
List<string> subfolders = Directory.GetDirectories(source).ToList();
foreach (var subfolder in subfolders)
{
OperateOnSourceFiles(subfolder, targetDir);
}
}
然后你的覆盖函数看起来像这样:
private static void OverWrite(string target, string sourcefile)
{
//Grab file name
var strSrcFile = sourcefile.Split(Path.DirectorySeparatorChar).Last();
//Search current target directory FILES, and copy only if same file name
List<string> targetfiles = Directory.GetFiles(target).Select(file=>file.Split(Path.DirectorySeparatorChar).Last()).ToList();
if (targetfiles.Contains(strSrcFile))
{
File.Copy(sourcefile, Path.Combine(target, Path.GetFileName(strSrcFile)), true);
}
//Recursively search current target directory SUBFOLDERS if any
List<string> subfolders = Directory.GetDirectories(target).ToList();
foreach (var subfolder in subfolders)
{
OverWrite(subfolder, sourcefile);
}
}
随意纠正我:)
注意:我意识到它仍然有很多foreach循环,但至少它们不是嵌套的,并且在调试时使生活更轻松。
答案 3 :(得分:0)
我喜欢这个主意,所以我自己试了一下。结果有点复杂然后我想它会。让我们深入研究,好吗?
基本思想是同步目录,因此我们希望引用DirectoryInfo
个实例。
var source = new DirectoryInfo(@"C:\SynchSource");
var target = new DirectoryInfo(@"C:\SynchTarget");
Synchronize(source, target);
Synchronize
几乎可以通过以下方式运作:
我的实现如下:
void Synchronize(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
SynchronizeFiles(sourceDir, targetDir);
SynchronizeDirectories(sourceDir, targetDir);
TraverseDirectories(sourceDir, targetDir);
}
注意.Single()
- 我们永远不能假设目录中只有一个人/进程在工作。
SynchronizeFiles
做了两件事:
void MoveFiles(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (FileInfo sourceFile in sourceDir.GetFiles())
{
string targetFilePath = Path.Combine(targetDir.FullName, sourceFile.Name);
File.Copy(sourceFile.FullName, targetFilePath);
}
}
void RemoveRedundantFiles(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (var targetFile in targetDir.GetFiles())
{
var sourceFilePath = Path.Combine(sourceDir.FullName, targetFile.Name);
if (!File.Exists(sourceFilePath))
{
targetFile.Delete();
}
}
}
我们现在可以假设当前目录中的所有文件都是相同的,不多也不少。为了遍历子目录,我们首先要确保目录结构是相同的。我们以与SynchronizeFiles
:
CreateMissingDirectories
)RemoveRedundantDirectories
)void CreateMissingDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (DirectoryInfo sourceSubDir in sourceDir.GetDirectories())
{
string targetSubDirPath = Path.Combine(targetDir.FullName, sourceSubDir.Name);
if (!Directory.Exists(targetSubDirPath))
{
Directory.CreateDirectory(targetSubDirPath);
}
}
}
void RemoveRedundantDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (DirectoryInfo targetSubDir in targetDir.GetDirectories())
{
string sourceSubDirPath = Path.Combine(sourceDir.FullName, targetSubDir.Name);
if (!Directory.Exists(sourceSubDirPath))
{
targetSubDir.Delete(true);
}
}
}
我们处于当前层次结构中的文件和目录相等的状态。我们现在可以遍历所有子目录并调用Synchronize:
void TraverseDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (DirectoryInfo sourceSubDir in sourceDir.GetDirectories())
{
DirectoryInfo targetSubDir = targetDir.GetDirectories(sourceSubDir.Name).Single();
Synchronize(sourceSubDir, targetSubDir);
}
}
我们已经完成了。
对于巨大的目录层次结构,大量或大型文件甚至是在目录中工作的并发进程,还有很大的改进空间。有很多工作要做,它要快(你可能想要缓存GetFiles
/ GetDirectories
),跳过不必要的File.Copy
调用(在假设副本之前获取文件哈希)需要)。
正如旁注:除了偶尔同步文件之外,根据需求,您可能需要查看FileSystemWatcher
,它可以在所选目录中递归检测所有更改。