Simant
Simant

Reputation: 4252

While copying file, when there is same file name but with different content is generating exception in C#

I am getting the exception

The process cannot access the file 'C:\Destination\New Text Document.txt' because it is being used by another process.

I need to copy all source files to the destination folder. When there is a same named file in Source and Destination I need to compare the Hash value to know whether both files have the same content. If same content found I need to skip the copying process but if the content is different I need to copy the file.

My class structure is as below:

using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace TestBackups
{
    public class FilesBackup
    {
        private string LookupDirectory;
        private string BackupDirectory;
        public FilesBackup()
        {
            LookupDirectory = "C:\\Source";
            BackupDirectory = "C:\\Destination";
        }

        public void PerformBackup()
        {
            DirSearch(LookupDirectory);         
        }

        public void DirSearch(string dir)
        {
            foreach (string file in Directory.GetFiles(dir))
            {
                // Console.WriteLine(string.Format("Filename : {0} and Lenghth : {1}", file, file.Length));
                string destFilePath = file.Replace(LookupDirectory, BackupDirectory);

                if (!File.Exists(file.Replace(LookupDirectory, BackupDirectory)))
                {
                    Console.WriteLine("DO Not Exists - copy file");
                    File.Copy(file, destFilePath);
                }
                else
                {
                    Console.WriteLine("Exists - check for the same content");

                    FileInfo sourceFile = new FileInfo(file);
                    FileInfo destinationFile = new FileInfo(destFilePath);

                    if (FilesAreEqual_Hash(sourceFile, destinationFile))
                    {
                        //Skip -Don't copy file
                    }
                    else
                    {
                        // Override the existing file                        
                        File.Copy(file, destFilePath, true);
                    }
                }
            }

            foreach (string d in Directory.GetDirectories(dir))
            {
                Console.WriteLine(d);
                DirSearch(d);
            }
        }

        public bool FilesAreEqual_Hash(FileInfo first, FileInfo second)
        {
            byte[] firstHash = MD5.Create().ComputeHash(first.OpenRead());
            byte[] secondHash = MD5.Create().ComputeHash(second.OpenRead());

            for (int i = 0; i < firstHash.Length; i++)
            {
                if (firstHash[i] != secondHash[i])
                    return false;
            }
            return true;
        }   

    }
}

The code is working file but when there is a same named file in destination but with different content inside, generating the exception.

My Console code is

using System;

namespace TestBackups
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {

                FilesBackup backup= new FilesBackup();                        
                backup.PerformBackup();    
                Console.ReadLine();
            }
            catch (Exception ex)
            {

            }
        }
    }
}

Upvotes: 0

Views: 439

Answers (1)

Dennis Rosenbaum
Dennis Rosenbaum

Reputation: 379

Filestream is a disposable type.

byte[] firstHash = MD5.Create().ComputeHash(first.OpenRead());
byte[] secondHash = MD5.Create().ComputeHash(second.OpenRead());

Try something like this:

byte[] firstHash, secondHash;
using (FileStream fs = File.OpenRead(first)) 
{
    firstHash = MD5.Create().ComputeHash(fs);
}
using (FileStream fs = File.OpenRead(second)) 
{
    secondHash = MD5.Create().ComputeHash(fs);
}

Upvotes: 2

Related Questions