Home > Back-end >  Sync actions in two folders locally c#
Sync actions in two folders locally c#

Time:03-05

I'm learning c# and i have a task to:
Sync content of the two directories. Given the paths of the two dirs - dir1 and dir2,then dir2 should be synchronized with dir 1:

  • If a file exists in dir1 but not in dir2,it should be copied
    -if a file exists in dir1 and in dir2,but content is changed,then file from dir1 should overwrite the one from dir2
    -if a file exists in dir2 but not in dir1 it should be removed
    Notes: files can be extremly large
    -dir1 can have nested folders
    hints:
    -read and write files async
    -hash files content and compare hashes not content

I have some logic on how to do this,but i dont know how to implement it.I googled the whole internet to get a point to start,but unsuccesseful.
I started with this:

using System.Security.Cryptography;

class Program
{
    static void Main(string[] args)
    {
        string sourcePath = @"C:\Users\artio\Desktop\FASassignment\root\dir1";
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";

        string[] dirsInSourcePath = Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories);
        string[] dirsInDestinationPath = Directory.GetDirectories(destinationPath, "*", SearchOption.AllDirectories);

        var filesInSourcePath = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories);
        var filesInDestinationPath = Directory.GetFiles(destinationPath,"*",SearchOption.AllDirectories);



        //Directories in source Path
        foreach (string dir in dirsInSourcePath)
        {
            Console.WriteLine("sourcePath:{0}", dir);
            Directory.CreateDirectory(dir);
        }

        //Directories in destination path
        foreach (string dir in dirsInDestinationPath)
        {
            Console.WriteLine("destinationPath:{0} ", dir);
        }

        //Files in source path
        foreach (var file in filesInSourcePath)
        {
            Console.WriteLine(Path.GetFileName(file));
        }

        //Files in destination path
        foreach (var file in filesInDestinationPath)
        {
            Console.WriteLine(Path.GetFileName(file));
        }
    }

}  

As i understand,i should check if in dir1 are some folders and files,if true,copy them in folder 2,and so on,but how to do this? i'm burning my head out two days already and have no idea.. please help.

Edit: For the first and second point i got a solution. :

public static void CopyFolderContents(string sourceFolder, string destinationFolder, string mask, Boolean createFolders, Boolean recurseFolders)
    {
        try
        {
            /*if (!sourceFolder.EndsWith(@"\")) { sourceFolder  = @"\"; }
            if (!destinationFolder.EndsWith(@"\")) { destinationFolder  = @"\"; }*/

            var exDir = sourceFolder;
            var dir = new DirectoryInfo(exDir);
            SearchOption so = (recurseFolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

            foreach (string sourceFile in Directory.GetFiles(dir.ToString(), mask, so))
            {
                FileInfo srcFile = new FileInfo(sourceFile);
                string srcFileName = srcFile.Name;

                // Create a destination that matches the source structure
                FileInfo destFile = new FileInfo(destinationFolder   srcFile.FullName.Replace(sourceFolder, ""));

                if (!Directory.Exists(destFile.DirectoryName) && createFolders)
                {
                    Directory.CreateDirectory(destFile.DirectoryName);
                }

                if (srcFile.LastWriteTime > destFile.LastWriteTime || !destFile.Exists)
                {
                    File.Copy(srcFile.FullName, destFile.FullName, true);
                }
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message   Environment.NewLine   Environment.NewLine   ex.StackTrace);
        }
    }  

It's not perfect,but it works.How this function should be improved: add async copy,and compare hashes of files not to copy again the identical ones. How to do it?

CodePudding user response:

So,after some time of much more research,i came up with this solution:

using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        string sourcePath = @"C:\Users\artio\Desktop\FASassignment\root\dir1";
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        var source = new DirectoryInfo(sourcePath);
        var destination = new DirectoryInfo(destinationPath);

        CopyFolderContents(sourcePath, destinationPath, "", true, true);
        DeleteAll(source, destination);
    }

    public static void CopyFolderContents(string sourceFolder, string destinationFolder, string mask, Boolean createFolders, Boolean recurseFolders)
    {
        try
        {

            var exDir = sourceFolder;
            var dir = new DirectoryInfo(exDir);
            var destDir = new DirectoryInfo(destinationFolder);

            SearchOption so = (recurseFolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

            foreach (string sourceFile in Directory.GetFiles(dir.ToString(), mask, so))
            {
                FileInfo srcFile = new FileInfo(sourceFile);
                string srcFileName = srcFile.Name;

                // Create a destination that matches the source structure
                FileInfo destFile = new FileInfo(destinationFolder   srcFile.FullName.Replace(sourceFolder, ""));

                if (!Directory.Exists(destFile.DirectoryName) && createFolders)
                {
                    Directory.CreateDirectory(destFile.DirectoryName);
                }

                //Check if src file was modified and modify the destination file
                if (srcFile.LastWriteTime > destFile.LastWriteTime || !destFile.Exists)
                {
                    File.Copy(srcFile.FullName, destFile.FullName, true);
                }
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message   Environment.NewLine   Environment.NewLine   ex.StackTrace);
        }
    }

    private static void DeleteAll(DirectoryInfo source, DirectoryInfo target)
    {
        if (!source.Exists)
        {
            target.Delete(true);
            return;
        }

        // Delete each existing file in target directory not existing in the source directory.
        foreach (FileInfo fi in target.GetFiles())
        {
            var sourceFile = Path.Combine(source.FullName, fi.Name);
            if (!File.Exists(sourceFile)) //Source file doesn't exist, delete target file
            {
                fi.Delete();
            }
        }

        // Delete non existing files in each subdirectory using recursion.
        foreach (DirectoryInfo diTargetSubDir in target.GetDirectories())
        {
            DirectoryInfo nextSourceSubDir = new DirectoryInfo(Path.Combine(source.FullName, diTargetSubDir.Name));
            DeleteAll(nextSourceSubDir, diTargetSubDir);
        }
    }
}  

It does everything it should,the only missing points are the async copy and sha comparison,but at least i have a solution.

  • Related