Last weekend I wrote a utility that does file synchronization (yes, I know there many such tools), but where I can define in advance what I want to see happen if there are discrepancies…  To do that, I needed a class that would take an array of file names from one folder and another array of files from another folder, and return files that are found in both folders and that are identical, e.g.:

 

var commonFiles = files1.Intersect(files2, new FileComparer(folder1, folder2)).ToList();

 

Here is the code of the FileComparer class:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace FileSync

{

    public class FileComparer : IEqualityComparer<string>

    {

        public enum ComparisonOptions

        {

            FileSizeAndDate = 0, // default

            Content = 1,

        }

 

        private string _folder1;

        private string _folder2;

        private ComparisonOptions _compOption;

 

        public FileComparer(string folder1, string folder2)

            : this(folder1, folder2, ComparisonOptions.FileSizeAndDate)

        {

 

        }

 

        public FileComparer(string folder1, string folder2, ComparisonOptions compOption)

        {

            _folder1 = NormalizedFolder(folder1);

            _folder2 = NormalizedFolder(folder2);

            _compOption = compOption;

        }

 

        public bool Equals(string x, string y)

        {

            bool result = false;

 

            System.IO.FileInfo fi1 = new System.IO.FileInfo(x);

            if (fi1.Exists)

            {

                System.IO.FileInfo fi2 = new System.IO.FileInfo(y);

                if (fi2.Name == fi1.Name && fi2.Exists && fi1.Length == fi2.Length) // note: contents can't be the same if the name or length is different

                {

                    if (_compOption == ComparisonOptions.FileSizeAndDate)

                    {

                        result = (fi1.LastWriteTimeUtc == fi2.LastWriteTimeUtc);

                    }

                    else

                    {

                        // TODO: for large files, read and compare in chunks

                        byte[] f1 = System.IO.File.ReadAllBytes(x);

                        byte[] f2 = System.IO.File.ReadAllBytes(y);

 

                        result = f1.Equals(f2);

                    }

                }

            }

 

           

            return result;

        }

 

        public int GetHashCode(string obj)

        {

            if (obj.StartsWith(_folder1))

                return obj.Substring(_folder1.Length).GetHashCode();

            else if (obj.StartsWith(_folder2))

                return obj.Substring(_folder2.Length).GetHashCode();

            else

                return 0;

        }

 

        public static string NormalizedFolder(string folder)

        {

            string result = String.Empty;

            if (!string.IsNullOrEmpty(folder) && !string.IsNullOrWhiteSpace(folder))

            {

                result = folder.Trim();

                if (result.EndsWith(@"\"))

                    result = result.Substring(0, result.Length - 1);

            }

            return result;

        }

    }

}