Копировать только новые или измененные файлы / каталоги в C # - PullRequest
0 голосов
/ 21 марта 2019

Я пытаюсь создать простое консольное приложение «копирование каталога / файла» в C #. Мне нужно скопировать все папки и файлы (сохраняя исходную иерархию) с одного диска на другой, как с диска C: \ Data на диск E: \ Data.

Однако я хочу, чтобы он только копировал НОВЫЕ или ИЗМЕНЕННЫЕ файлы из источника в место назначения. Если файл на целевом диске более новый, чем файл на исходном диске, он не копируется.

(проблема)

В коде, который у меня есть, он сравнивает файл "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));  
        }  
    }  
}  

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Обновление:

Я изменил свой код с предложениями выше, и все прошло хорошо.Это произошло именно так, как я ожидал.

Однако проблема, с которой я столкнулся, заключалась в том, сколько времени потребовалось для запуска приложения в большой папке.(содержит 6000 файлов и 5 подпапок)

В небольшой папке (28 файлов в 5 подпапках) для запуска потребовалось всего несколько секунд.Но для большой папки потребовалось 35 минут, чтобы обработать только 1300 файлов.

Решение:

Приведенный ниже код сделает то же самое, но гораздо быстрее.Эта новая версия обработала 6000 файлов примерно за 10 секунд.Он обработал 40 000 файлов за 1 минуту и ​​50 секунд.

Что этот новый код делает (и не делает)

Если папка назначения пуста, скопируйте все из источника вприемник.

Если у адресата есть некоторые или все те же файлы / папки, что и у источника, сравните и скопируйте все новые или измененные файлы из источника в адресат.

Если конечный файл новее исходного, не копируйте.

Итак, вот код, чтобы это произошло.Наслаждайтесь и делитесь.

Спасибо всем, кто помог мне лучше понять это.



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

0 голосов
/ 21 марта 2019

Вы можете просто взять массив файлов в «источнике» и проверить соответствие имени в «месте назначения»

/// <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;
    }
...