比较不同文件的两个文件夹?

时间:2010-12-08 11:46:02

标签: c# linq

     var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories).Select(x => new { x.Name, x.Length });
    var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories).Select(x => new { x.Name, x.Length });
    var onlyIn1 = dir1Files.Except(dir2Files).Select(x => new { x.Name });
    File.WriteAllLines(@"d:\log1.txt", foo1);

这里我将根据名称和文本文件中的两个文件进行比较... 但我需要写名字和目录名...但我不能选择像这样的目录名

 var onlyIn1 = dir1Files.Except(dir2Files).Select(x => new { x.Name,x.DirectoryName });

有什么建议吗?

1 个答案:

答案 0 :(得分:3)

使用FullName解决您的问题吗?

var onlyIn1 = dir1Files.Except(dir2Files).Select(x => new { x.FullName }); 

或者,您可以在Select语句中组合自定义字符串:

// get strings in the format "file.ext, c:\path\to\file"
var onlyIn1 = dir1Files.Except(dir2Files).Select(x => 
                  string.Format("{0}, {1}", x.Name, x.Directory.FullName)); 

为了能够在对象中使用此信息,请不要在第一步中创建信息有限的匿名类型,而是保留完整的FileInfo个对象:

var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories);
var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories);

<强>更新
代码示例中的真正问题是Except将使用默认相等比较器进行比较。对于大多数类型(当然在匿名类型的情况下),这意味着它将比较对象引用。由于您有两个包含FileInfo个对象的列表,Except将返回第一个列表中的所有对象,其中第二个列表中找不到相同的对象实例。由于第一个列表中的所有对象实例都不存在于第二个列表中,因此将返回第一个列表中的所有对象。

为了解决这个问题(并且仍然可以访问您要存储的数据),您需要使用Except overload that accepts an IEqualityComparer<T>。首先,让我们创建IEqualityComparer

class FileInfoComparer : IEqualityComparer<FileInfo>
{
    public bool Equals(FileInfo x, FileInfo y)
    {
        // if x and y are the same instance, or both are null, they are equal
        if (object.ReferenceEquals(x,y))
        {
            return true;
        }
        // if one is null, they are not equal
        if (x==null || y == null)
        {
            return false;
        }
        // compare Length and Name
        return x.Length == y.Length && 
            x.Name.Equals(y.Name, StringComparison.OrdinalIgnoreCase);
    }

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

现在您可以使用该比较器来比较目录中的文件:

var dir1 = new DirectoryInfo(@"c:\temp\a");
var dir2 = new DirectoryInfo(@"c:\temp\b");

var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories); 
var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories); 

var onlyIn1 = dir1Files
    .Except(dir2Files, new FileInfoComparer())
    .Select(x =>  string.Format("{0}, {1}", x.Name, x.Directory.FullName));