比较两个任意格式的文件c#

本文关键字:格式 文件 任意 两个 比较 | 更新日期: 2023-09-27 18:28:18

我正在开发一个应用程序,该应用程序接收文件的两个文件夹中的任何一个,并将它们相互比较,并输出任何差异。我有一个部分,它获取两个文件的内容,然后输出文件名中的任何差异。现在,我想将两个文件夹中相同的文件进行比较,看看它们是否不同。我的第一个猜测是检查它们,看看二进制文件是否使用了字节读取器,我一直在尝试,但无法正常工作。我在下面找到了一个解决方案,但无法使其发挥作用。有人有一个起点或一些示例代码让我开始吗。我想尝试使它对任何文件类型都通用。即文本、docx、exe、pdf、mp3、mp4、xlsx。。。

static void Main(string[] args)
    {
        // Read the file into <bits>
        try
        {
            var fs = new FileStream(Console.ReadLine(), FileMode.Open);
            var len = (int)fs.Length;
            var bits = new byte[len];
            fs.Read(bits, 0, len);
            // Dump 16 bytes per line
            for (int ix = 0; ix < len; ix += 16)
            {
                var cnt = Math.Min(16, len - ix);
                var line = new byte[cnt];
                Array.Copy(bits, ix, line, 0, cnt);
                // Write address + hex + ascii
                Console.Write("{0:X6}  ", ix);
                Console.Write(BitConverter.ToString(line));
                Console.Write("  ");
                // Convert non-ascii characters to .
                for (int jx = 0; jx < cnt; ++jx)
                    if (line[jx] < 0x20 || line[jx] > 0x7f) line[jx] = (byte)'.';
                Console.WriteLine(Encoding.ASCII.GetString(line));
                Console.Read();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            Console.ReadLine();
        }
    }

比较两个任意格式的文件c#

在我看来,另一种更简单的方法是使用MD5哈希:

        string filePath = @"C:'Users'Gabriel'Desktop'Test.txt";
        string filePath2 = @"C:'Users'Gabriel'Desktop'Test2.txt";
        string hash;
        string hash2;
        using (var md5 = MD5.Create())
        {
            using (var stream = File.OpenRead(filePath))
            {
                hash = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
            }
            using (var stream = File.OpenRead(filePath2))
            {
                hash2 = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
            }
        }
        if (hash == hash2)
        {
            // Both files are the same, so you can do your stuff here
        }

请注意,MD5哈希使用文件的内容来定义它们是否相同,但它不考虑其名称。因此,如果您创建了两个具有不同名称的相同文本文件,则会认为它们是相同的。如果你也需要它来检查名称,你可以尝试将最后一个If语句更改为类似的内容:

        if (hash == hash2)
        {
            FileInfo file = new FileInfo(filePath);
            FileInfo file2 = new FileInfo(filePath2);
            if (file.Name == file2.Name)
            {
                // Both files are the same, so you can do your stuff here
            }
        }

这个类可能对比较文件有用:

public class FileComparator
{
    private const int _bufferCapacity = 0x400000; //4Mb
    public static bool AreEquals(string first, string second)
    {
        return AreEquals(File.OpenRead(first), File.OpenRead(second));
    }
    public static bool AreEquals(FileStream first, FileStream second)
    {
        using (var firstStream = new BufferedStream(first))
        using (var secondStream = new BufferedStream(second))
        {
            if (first.Length != second.Length)
                return false;
            var firstBuffer = new byte[_bufferCapacity];
            var secondBuffer = new byte[_bufferCapacity];
            int bytesReadFirst;
            int bytesReadSecond;
            do
            {
                bytesReadFirst = firstStream.Read(firstBuffer, 0, firstBuffer.Length);
                bytesReadSecond = secondStream.Read(secondBuffer, 0, secondBuffer.Length);
                if (bytesReadFirst != bytesReadSecond || !CompareByteArrays(firstBuffer, secondBuffer))
                    return false;
            } while (bytesReadFirst > 0 && bytesReadSecond > 0);
            return true;
        }
    }

    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int memcmp(byte[] b1, byte[] b2, long count);
    private static bool CompareByteArrays(byte[] first, byte[] second)
    {
        return first.Length == second.Length && memcmp(first, second, first.Length) == 0;
    }
}

您可以通过将文件名作为参数或仅作为流传递来使用它:

var result = FileComparator.AreEquals(Console.ReadLine(), Console.ReadLine());

如果不想在代码中使用"DllImport",可以用SequanceEquals的调用来填充它,但速度会慢得多。