2013-05-08 67 views
4

我想比较两个目录来看到的是目录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(); 
    } 
} 

但是,这仍然不起作用。你可以看到我评论了另一个尝试,只是在比较中把所有的东西都做成大写,但它不会那么做。

+1

FileInfo还包含日期和时间信息。你不应该只是比较文件名吗? – rene 2013-05-08 19:52:19

+0

您确定文件名中没有小的差异吗? – tnw 2013-05-08 19:52:37

+3

我不认为'System.IO.FileInfo'的'Equals()'方法是你想要的。你为什么不定义文件“已经[在]目录2中”的含义?你的意思是同一个文件名吗?完全相同的字节? – rliu 2013-05-08 19:53:38

回答

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); 
+0

这是我第一次尝试它的方式,它也不起作用。所以我尝试了更简单的方法。两者仍然返回两个目录中存在的文件,我只想看到目录1中的文件。 – 2013-05-08 20:21:05

+0

@RobertWiglesworth此解决方案将会很好,您只需在比较器中进行不区分大小写的比较。 'String.Compare(f1.Name,f2.Name,StringComparison.OrdinalIgnoreCase)== 0' – 2013-05-08 20:43:21

+0

@LeeHiles如果你想要,使用'String.Equals(f1.Name,f2.Name,StringComparison.OrdinalIgnoreCase)'。 – 2013-05-08 20:54:04

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) 

或在比较之前将所有内容转换为小写。

+0

这仍然显示列表1中的所有文件,即使它们存在于列表2中。 – 2013-05-08 20:24:15

+0

这很奇怪...您确定名称完全相同吗? (同样的情况下,没有额外的空间) – 2013-05-08 20:29:11

+0

好的,这里有些奇怪的......我试着用Intersect来看看它是否列出了相同的东西。我有一个价值。这是为了确保我具有正确的文件夹权限,我手动从目录1复制到目录2的文件。我检查了它们的属性,dir 1将它们显示为文件类型.prn和dir 2将它们显示为文件类型.PRN。这是系统偏好还是什么? – 2013-05-08 20:32:06

0

既然你只在兴趣,投射到名的序列的序列与LINQ的.Select扩展方法:(你可以使用var,隐式类型)

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); 

这是有效的,因为string默认的相等比较器做了序数和区分大小写的比较(不仅仅是像FileInfo类一样引用相等比较)。