我正在尝试比较两个目录,以查看目录1中不在目录2中的文件。我有以下代码:
System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(pathA);
System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(pathB);
IEnumerable<System.IO.FileInfo> list1 = dir1.GetFiles("*.PRN");
IEnumerable<System.IO.FileInfo> list2 = dir2.GetFiles("*.PRN");
IEnumerable<System.IO.FileInfo> list3 = list1.Except(list2);
Console.WriteLine("The following files are in list1 but not list2:");
foreach (var v in list3)
{
Console.WriteLine(v);
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
当它运行时,它清楚地列出目录1中的所有文件,但其中许多已经在目录2中。我可以通过查看Windows资源管理器并查看文件名来看到这一点。我错过了什么?
编辑:
我认为问题出在文件比较部分。我试图让它忽略文件扩展名的情况。我试过这个:
class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
{
public FileCompare() { }
public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
{
//return (f1.Name.ToUpper == f2.Name.ToUpper &&
// f1.Length == f2.Length);
return (string.Equals(f1.Name, f2.Name, StringComparison.OrdinalIgnoreCase) && f1.Length == f2.Length);
}
public int GetHashCode(System.IO.FileInfo fi)
{
string s = String.Format("{0}{1}", fi.Name, fi.Length);
return s.GetHashCode();
}
}
但这仍然无效。你可以看到我评论了另一种尝试,只是在比较中把所有东西都做大写,但它不会那样。
答案 0 :(得分:7)
您将需要使用Except()
的重载版本并向其传递IEqualityComparer
的自定义实现,该实现明确指出了定义两个FileInfo
对象的完全匹配的标准
请参阅此处的示例并根据您自己的需要进行修改: http://msdn.microsoft.com/en-us/library/bb336390.aspx
答案 1 :(得分:2)
MSDN上有一个示例,向您展示如何执行此操作。
创建您的IEqualityComparer
实施
class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
{
public FileCompare() { }
public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
{
return (f1.Name == f2.Name &&
f1.Length == f2.Length);
}
public int GetHashCode(System.IO.FileInfo fi)
{
string s = String.Format("{0}{1}", fi.Name, fi.Length);
return s.GetHashCode();
}
}
然后使用比较器的Except
重载。
var queryList1Only = (from file in list1
select file).Except(list2, myFileCompare);
答案 2 :(得分:0)
您可以使用LINQ
var list3 = from c in list1
where !(from o in list2
select o.Name)
.Contains(c.Name)
select c;
可能还存在不同情况的问题
你可以尝试
.Equals(c.Name, StringComparison.OrdinalIgnoreCase)
而不是
.Contains(c.Name)
或者在比较之前将所有内容转换为小写。
答案 3 :(得分:0)
由于您只对名称感兴趣,所以使用LINQ的.Select
扩展方法将序列投影到名称序列:
IEnumerable<string> list1 = dir1.GetFiles("*.PRN").Select(fi => fi.Name);
IEnumerable<string> list2 = dir2.GetFiles("*.PRN").Select(fi => fi.Name);
IEnumerable<string> list3 = list1.Except(list2);
(您可以使用var
隐式输入。)
这适用于string
的默认相等比较器进行序数和区分大小写的比较(不仅仅是FileInfo
类附带的引用相等比较)。