簡體   English   中英

在 C# 中僅復制新的或修改過的文件/目錄

[英]Copy only new or modified files/directories in C#

我正在嘗試在 C# 中創建一個簡單的“目錄/文件復制”控制台應用程序。我需要的是將所有文件夾和文件(保持原始層次結構)從一個驅動器復制到另一個驅動器,例如從驅動器 C:\\Data 復制到驅動器 E :\\數據。

但是,我只希望它將任何 NEW 或 MODIFIED 文件從源復制到目標。 如果目標驅動器上的文件比源驅動器上的文件新,則不會復制。

(問題)

在我擁有的代碼中,它將源中的文件“abc.pdf”與目標中的文件“xyz.pdf”進行比較,因此即使目標文件較新,也會用源中的任何內容覆蓋目標文件。 我想弄清楚如何將源中的“abc.pdf”與目標中的“abc.pdf”進行比較。

如果我將源和目標向下鑽取到特定文件,這會起作用,但是當我返回到文件夾級別時,它會用源文件覆蓋目標文件,即使目標文件較新。

(我的解決方案 - 沒有用)

我想通過將“if (file.LastWriteTime > destination.LastWriteTime)”放在“foreach”命令之后,它會比較兩個文件夾中的文件,File1 源文件和 File1 目標文件,但事實並非如此。

似乎我在“FileInfo[]”、“foreach”或“if”語句中遺漏了一些東西來進行一對一的比較。 我想可能是對“Path.Combine”語句或“SearchOption.AllDirectories”的一些引用,但我不確定。

有什么建議?

正如您從我的基本代碼示例中看到的,我是 C# 新手,所以請用簡單的術語回答您的問題。

謝謝你。

這是我嘗試過的代碼,但它不起作用。


class Copy  
{  
    public static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination)  
    {  
        if (!destination.Exists)  
        {  
            destination.Create();  
        }  
        // Copy files.  
        FileInfo[] files = source.GetFiles();  
        FileInfo[] destFiles = destination.GetFiles();  
        foreach (FileInfo file in files)  
            foreach (FileInfo fileD in destFiles)  
                // Copy only modified files    
                    if (file.LastWriteTime > fileD.LastWriteTime)  
                    {  
                        file.CopyTo(Path.Combine(destination.FullName,  
                        file.Name), true);  
                    }  

                // Copy all new files  
                else  
                if (!fileD.Exists)  
                {  
                    file.CopyTo(Path.Combine(destination.FullName, file.Name), true);  
                }  
        // Process subdirectories.  
        DirectoryInfo[] dirs = source.GetDirectories();  
        foreach (DirectoryInfo dir in dirs)  
        {  
            // Get destination directory.  
            string destinationDir = Path.Combine(destination.FullName, dir.Name);  
            // Call CopyDirectory() recursively.  
            CopyDirectory(dir, new DirectoryInfo(destinationDir));  
        }  
    }  
}  

您可以只獲取“源”中的文件數組並檢查“目標”中的匹配名稱

/// <summary>
    /// checks whether the target file needs an update (if it doesn't exist: it needs one)
    /// </summary>
    public static bool NeedsUpdate(FileInfo localFile, DirectoryInfo localDir, DirectoryInfo backUpDir)
    {
        bool needsUpdate = false;

        if (!File.Exists(Path.Combine(backUpDir.FullName, localFile.Name)))
        {
            needsUpdate = true;
        }
        else
        {
            FileInfo backUpFile = new FileInfo(Path.Combine(backUpDir.FullName, localFile.Name));

            DateTime lastBackUp = backUpFile.LastWriteTimeUtc;
            DateTime lastChange = localFile.LastWriteTimeUtc;

            if (lastChange != lastBackUp)
            {
                needsUpdate = true;
            }
            else
            {/*no change*/}
        }
        return needsUpdate;
    }

更新:

我用上面的建議修改了我的代碼,一切順利。 它完全符合我的預期。

但是,我遇到的問題是在大文件夾上運行應用程序所花費的時間。 (包含 6,000 個文件和 5 個子文件夾)

在一個小文件夾上,(5 個子文件夾中的 28 個文件)運行只需要幾秒鍾。 但是,在較大的文件夾中,僅處理 1,300 個文件需要 35 分鍾。

解決方案:

下面的代碼將做同樣的事情,但速度要快得多。 這個新版本在大約 10 秒內處理了 6,000 個文件。 它在大約 1 分 50 秒內處理了 40,000 個文件。

這個新代碼做什么(和不做什么)

如果目標文件夾為空,則將所有內容從源復制到目標。

如果目標具有與源相同的部分或全部文件/文件夾,則比較並將任何新的或修改過的文件從源復制到目標。

如果目標文件比源文件新,請不要復制。

所以,這是實現它的代碼。 享受和分享。

感謝所有幫助我更好地理解這一點的人。



    using System;
    using System.IO;


    namespace VSU1vFileCopy
    {
        class Program
        {
            static void Main(string[] args)
            {
                const string Src_FOLDER = @"C:\Data";
                const string Dest_FOLDER = @"E:\Data";
                string[] originalFiles = Directory.GetFiles(Src_FOLDER, "*", SearchOption.AllDirectories);

                Array.ForEach(originalFiles, (originalFileLocation) =>
                {
                    FileInfo originalFile = new FileInfo(originalFileLocation);
                    FileInfo destFile = new FileInfo(originalFileLocation.Replace(Src_FOLDER, Dest_FOLDER));

                    if (destFile.Exists)
                    {
                        if (originalFile.Length > destFile.Length)
                        {
                            originalFile.CopyTo(destFile.FullName, true);
                        }
                    }
                    else
                    {
                        Directory.CreateDirectory(destFile.DirectoryName);
                        originalFile.CopyTo(destFile.FullName, false);
                    }
                });
            }
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM