如何在c#中将一个文件集合与另一个文件集合进行比较?

时间:2009-12-06 10:59:56

标签: c# fileinfo directoryinfo

我正在学习C#(现在已经习惯了2天了)我已经决定,为了学习目的,我将重建一个我在VB6中制作的用于同步文件的旧应用程序(通常是通过网络)

当我在VB 6中编写代码时,它的工作方式大致如下:

  1. 创建Scripting.FileSystemObject
  2. 为源和目标创建目录对象
  3. 为源和目标创建文件列表对象
  4. 遍历源对象,并检查它是否存在于目标中
    • 如果没有,请创建
    • 如果是,请检查源版本是否更新/更大,如果是,则覆盖其他
  5. 到目前为止,这就是我所拥有的:

    private bool syncFiles(string sourcePath, string destPath) {
        DirectoryInfo source = new DirectoryInfo(sourcePath);
        DirectoryInfo dest = new DirectoryInfo(destPath);
    
        if (!source.Exists) {
            LogLine("Source Folder Not Found!");
            return false;
        }
    
        if (!dest.Exists) {
            LogLine("Destination Folder Not Found!");
            return false;
        }
    
        FileInfo[] sourceFiles = source.GetFiles();
        FileInfo[] destFiles = dest.GetFiles();
    
        foreach (FileInfo file in sourceFiles) {
            // check exists on file
        }
    
        if (optRecursive.Checked) {
            foreach (DirectoryInfo subDir in source.GetDirectories()) {
                // create-if-not-exists destination subdirectory
                syncFiles(sourcePath + subDir.Name, destPath + subDir.Name);
            }
        }
        return true;
    }
    

    我已经阅读过似乎主张使用FileInfo或DirectoryInfo对象来检查“Exists”属性的示例,但我特意寻找一种方法来搜索现有的文件集合/列表,而不是实时检查每个文件的文件系统,因为我将通过网络这样做并不断回到一个数千个文件目录是缓慢的慢。

    先谢谢。

2 个答案:

答案 0 :(得分:5)

GetFiles()方法只会获取确实存在的文件。它不构成不存在的随机文件。所以你要做的就是检查它是否存在于另一个列表中。

这可能有用:

var sourceFiles = source.GetFiles();
var destFiles = dest.GetFiles();

foreach (var file in sourceFiles)
{
    if(!destFiles.Any(x => x.Name == file.Name))
    {
        // Do whatever
    }
}

注意: 在完成对GetFiles()的调用后,您当然无法保证某些内容未发生变化。例如,如果您稍后尝试复制文件,则可能已删除或重命名该文件。


也许可以通过使用Except方法或类似方法以某种方式更好地完成。例如:

var sourceFiles = source.GetFiles();
var destFiles = dest.GetFiles();

var sourceFilesMissingInDestination = sourceFiles.Except(destFiles, new FileNameComparer());

foreach (var file in sourceFilesMissingInDestination)
{
    // Do whatever
}

FileNameComparer的实现方式如下:

public class FileNameComparer : IEqualityComparer<FileInfo>
{
    public bool Equals(FileInfo x, FileInfo y)
    {
        return Equals(x.Name, y.Name);
    }


    public int GetHashCode(FileInfo obj)
    {
        return obj.Name.GetHashCode();
    }
}     

虽然未经测试:p

答案 1 :(得分:4)

一个小细节,而不是

 sourcePath + subDir.Name

我会用

 System.IO.Path.Combine(sourcePath, subDir.Name)

Path在文件和文件名上执行可靠的,独立于操作系统的操作。

此外,我注意到optRecursive.Checked突然冒出来。作为一个好的设计问题,请将其作为参数:

bool syncFiles(string sourcePath, string destPath, bool checkRecursive)

既然你提到它可能用于大量文件,请留意.NET 4,它有一个IEnumerable替代GetFiles(),它可以让你以流媒体方式处理它。