一个文件比较的工具

起因

写代码有时,需要对比一下文件是改动了,就写了这工具。其实用SVN 或者GIT比较也很方便。

实现

 private void button1_Click(object sender, EventArgs e)
        {
            var comparer = new DirectoryFileComparer();
            // 比较两个目录,将结果保存到指定文件
            comparer.CompareCommonFiles(
               textBox1.Text.Trim(),  // 源目录
               textBox2.Text.Trim(),  // 目标目录
                @"d:\filechanges.txt"   // 结果输出文件
            );
        }

CompareCommonFiles的处理   

 找出两个目录都存在但内容不同的文件
 var differentFiles = FindCommonButDifferentFiles(sourceDir, targetDir, sourceFiles, targetFiles);

需要比较的文件扩展名

private readonly string[] _targetExtensions = { ".cs", ".aspx", ".js" };

比较文件

            foreach (var relativePath in commonFiles)
            {
                var sourceFilePath = sourceDir + "" + relativePath;// Path.Combine(sourceDir, relativePath);
                var targetFilePath = targetDir + "" + relativePath; //Path.Combine(targetDir, relativePath);
                if (File.Exists(sourceFilePath))
                    if (File.Exists(targetFilePath))
                    {
                        string s1 = System.IO.File.ReadAllText(sourceFilePath);
                        string s2 = System.IO.File.ReadAllText(targetFilePath);
                        if (s1!=s2)
                            differentFiles.Add(relativePath);
                        // 比较文件内容
                        //if (!FilesContentsEqual(sourceFilePath, targetFilePath))
                        //{
                        //    differentFiles.Add(relativePath);
                        //}
                    }
            }

FilesContentsEqual的处理

可能有人会问为啥不用MD5 进行比较?

在这里用MD5 如果是大文件的话,其实更慢,而且也没有必要。

/// <summary>
        /// 比较两个文件的内容是否相同
        /// </summary>
        private bool FilesContentsEqual(string path1, string path2)
        {
           
            // 先比较文件大小,不同则内容肯定不同
            var fileInfo1 = new FileInfo(path1);
            var fileInfo2 = new FileInfo(path2);

            if (fileInfo1.Length != fileInfo2.Length)
                return false;

            // 对于空文件,直接返回相同
            if (fileInfo1.Length == 0)
                return true;

            // 比较文件内容(使用缓冲流提高效率)
            using (var stream1 = fileInfo1.OpenRead())
            using (var stream2 = fileInfo2.OpenRead())
            {
                const int bufferSize = 8192;
                byte[] buffer1 = new byte[bufferSize];
                byte[] buffer2 = new byte[bufferSize];

                int bytesRead;
                while ((bytesRead = stream1.Read(buffer1, 0, bufferSize)) > 0)
                {
                    // 读取第二个文件的相同字节数
                    int bytesRead2 = stream2.Read(buffer2, 0, bufferSize);

                    // 如果读取的字节数不同,文件内容不同
                    if (bytesRead != bytesRead2)
                        return false;

                    // 比较缓冲区内容
                    for (int i = 0; i < bytesRead; i++)
                    {
                        if (buffer1[i] != buffer2[i])
                            return false;
                    }
                }
            }

            return true;
        }
 

代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DirComparer
{
    public class DirectoryFileComparer
    {
        // 需要比较的文件扩展名
        private readonly string[] _targetExtensions = { ".cs", ".aspx", ".js" };

        /// <summary>
        /// 比较两个目录,找出共同存在但内容不同的文件
        /// </summary>
        /// <param name="sourceDir">源目录路径</param>
        /// <param name="targetDir">目标目录路径</param>
        /// <param name="outputFile">结果输出文件路径</param>
        /// <returns>是否成功完成比较</returns>
        public bool CompareCommonFiles(string sourceDir, string targetDir, string outputFile)
        {
            try
            {
                // 验证目录是否存在
                if (!Directory.Exists(sourceDir))
                {
                    Console.WriteLine($"源目录不存在: {sourceDir}");
                    return false;
                }

                if (!Directory.Exists(targetDir))
                {
                    Console.WriteLine($"目标目录不存在: {targetDir}");
                    return false;
                }

                // 获取两个目录中符合条件的所有文件
                var sourceFiles = GetFilesWithExtensions(sourceDir);
                var targetFiles = GetFilesWithExtensions(targetDir);

                // 找出两个目录都存在但内容不同的文件
                var differentFiles = FindCommonButDifferentFiles(sourceDir, targetDir, sourceFiles, targetFiles);

                // 保存结果到文件
                SaveResults(differentFiles, outputFile);

                Console.WriteLine($"比较完成,共发现 {differentFiles.Count} 个共同存在但内容不同的文件,结果已保存到 {outputFile}");
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"比较过程中发生错误: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 获取目录中指定扩展名的所有文件(相对路径)
        /// </summary>
        private List<string> GetFilesWithExtensions(string directory)
        {
            var files = new List<string>();

            foreach (var ext in _targetExtensions)
            {
                // 获取所有符合扩展名的文件,包括子目录
                files.AddRange(Directory.GetFiles(directory, $"*{ext}", SearchOption.AllDirectories));
            }

            // 转换为相对于根目录的路径,便于比较
            return files.Select(file => file.Substring(directory.Length)).ToList();
        }

        /// <summary>
        /// 找出两个目录都存在但内容不同的文件
        /// </summary>
        private List<string> FindCommonButDifferentFiles(string sourceDir, string targetDir,
                                                      List<string> sourceFiles, List<string> targetFiles)
        {
            var differentFiles = new List<string>();

            // 找出两个目录都存在的文件
            var commonFiles = sourceFiles.Intersect(targetFiles);

            foreach (var relativePath in commonFiles)
            {
                var sourceFilePath = sourceDir + "" + relativePath;// Path.Combine(sourceDir, relativePath);
                var targetFilePath = targetDir + "" + relativePath; //Path.Combine(targetDir, relativePath);
                if (File.Exists(sourceFilePath))
                    if (File.Exists(targetFilePath))
                    {
                        string s1 = System.IO.File.ReadAllText(sourceFilePath);
                        string s2 = System.IO.File.ReadAllText(targetFilePath);
                        if (s1!=s2)
                            differentFiles.Add(relativePath);
                        // 比较文件内容
                        //if (!FilesContentsEqual(sourceFilePath, targetFilePath))
                        //{
                        //    differentFiles.Add(relativePath);
                        //}
                    }
            }

            return differentFiles;
        }

        /// <summary>
        /// 比较两个文件的内容是否相同
        /// </summary>
        private bool FilesContentsEqual(string path1, string path2)
        {
           
            // 先比较文件大小,不同则内容肯定不同
            var fileInfo1 = new FileInfo(path1);
            var fileInfo2 = new FileInfo(path2);

            if (fileInfo1.Length != fileInfo2.Length)
                return false;

            // 对于空文件,直接返回相同
            if (fileInfo1.Length == 0)
                return true;

            // 比较文件内容(使用缓冲流提高效率)
            using (var stream1 = fileInfo1.OpenRead())
            using (var stream2 = fileInfo2.OpenRead())
            {
                const int bufferSize = 8192;
                byte[] buffer1 = new byte[bufferSize];
                byte[] buffer2 = new byte[bufferSize];

                int bytesRead;
                while ((bytesRead = stream1.Read(buffer1, 0, bufferSize)) > 0)
                {
                    // 读取第二个文件的相同字节数
                    int bytesRead2 = stream2.Read(buffer2, 0, bufferSize);

                    // 如果读取的字节数不同,文件内容不同
                    if (bytesRead != bytesRead2)
                        return false;

                    // 比较缓冲区内容
                    for (int i = 0; i < bytesRead; i++)
                    {
                        if (buffer1[i] != buffer2[i])
                            return false;
                    }
                }
            }

            return true;
        }

        /// <summary>
        /// 将比较结果保存到文件
        /// </summary>
        private void SaveResults(List<string> differentFiles, string outputFile)
        {
            // 确保输出目录存在
            var outputDir = Path.GetDirectoryName(outputFile);
            if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir))
            {
                Directory.CreateDirectory(outputDir);
            }

            // 写入结果,包含时间戳
            using (var writer = new StreamWriter(outputFile))
            {
                writer.WriteLine($"两个目录中共同存在但内容不同的文件 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
                writer.WriteLine("==========================================");
                writer.WriteLine();

                if (differentFiles.Count == 0)
                {
                    writer.WriteLine("未发现共同存在但内容不同的文件");
                }
                else
                {
                    foreach (var file in differentFiles)
                    {
                        writer.WriteLine(file);
                    }
                }
            }
        }
    }

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月巴月巴白勺合鸟月半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值