2013-05-08 71 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類一樣引用相等比較)。