2009-12-06 50 views
0

我剛剛學習C#(已經擺弄它大約2天了),並且我已經決定,爲了學習目的,我將重建一個我在VB6中用於同步文件(通常通過網絡)的舊應用程序。如何在C#中將一個文件集合與另一個文件進行比較?

當我在VB 6編寫的代碼,它的工作大致是這樣的:

  1. 創建Scripting.FileSystemObject
  2. 源和目的地創建目錄對象
  3. 創建文件,列出了源對象和目的地
  4. 遍歷源對象,並檢查它是否存在於目標中
    • 如果沒有,創建它
    • 如果是這樣,請檢查源版本更新/大,如果是這樣,覆蓋其他

到目前爲止,這是我所:

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的對象做檢查的「存在」屬性倡導的例子,但我特別尋找一種方式來搜索文件的現有集合/列表,而不是對每個文件的文件系統進行實時檢查,因爲我會這樣做所以在整個網絡中不斷回溯到數千個文件目錄的速度緩慢緩慢。

在此先感謝。

回答

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

+4

也爲子目錄使用Path.Combine(sourcePath,subDir.Name),而不是sourcePath + subDir.Name – 2009-12-06 11:11:55

+0

也看看GetFileSystemInfos方法:http://msdn.microsoft.com/en-us/庫/ system.io.directoryinfo.getfilesysteminfos.aspx – Svish 2009-12-06 11:15:11

+0

至於你的筆記:我明白了,但它是我承擔了風險,前期投資獲取文件列表的操作,所以我沒有做單獨存在於許許多多的檢查 - 千個文件。非常感謝您的回答,我想查看「Any」的語法! – Dereleased 2009-12-06 11:19:24

4

一個小細節,而不是

sourcePath + subDir.Name 

我將使用

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

Path對文件和文件夾名稱的操作是可靠的,與操作系統無關的操作。

另外我注意到optRecursive.Checked冒出來的地方。由於良好的設計問題,使該參數:

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

既然你提到它可以用於大量文件,留意對.NET 4,它具有的GetFiles一個IEnumerable更換( ),它可以讓你以流媒體的方式處理這個問題。

+0

+1,感謝您的建議! – Dereleased 2009-12-06 11:19:57

+0

+1指出「既然你提到它可以用於大量文件,留意對.NET 4,它具有的GetFiles(),可以讓你以流方式處理這一個IEnumerable替代品。」 – sehe 2011-03-23 20:52:54

+0

+1使用'Path.Combine'可以讓你圍繞那些結束的斜線在那裏而且有時不在那裏的問題。這讓生活變得很痛苦。 – ErocM 2013-12-11 20:06:55

相關問題