如何使用.NET快速比较2个文件?

问题描述 投票:119回答:18

Typical approaches建议通过FileStream读取二进制文件并逐字节地比较它。

  • CRC校验和比较会更快吗?
  • 是否有任何.NET库可以为文件生成校验和?
c# file compare checksum
18个回答
108
投票

校验和比较很可能比逐字节比较慢。

为了生成校验和,您需要加载文件的每个字节,并对其执行处理。然后,您必须在第二个文件上执行此操作。处理几乎肯定比比较检查慢。

至于生成校验和:您可以使用加密类轻松完成此操作。这是一个带C#的short example of generating an MD5 checksum

但是,如果您可以预先计算“测试”或“基础”案例的校验和,则校验和可能更快并且更有意义。如果您有一个现有文件,并且您正在检查新文件是否与现有文件相同,那么预先计算“现有”文件上的校验和意味着只需要执行一次DiskIO,新文件。这可能比逐字节比较更快。


2
投票

我的答案是@lars的衍生物,但修复了Stream.Read调用中的错误。我还添加了一些其他答案的快速路径检查,以及输入验证。简而言之,这应该是答案:

using System;
using System.IO;

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            var fi1 = new FileInfo(args[0]);
            var fi2 = new FileInfo(args[1]);
            Console.WriteLine(FilesContentsAreEqual(fi1, fi2));
        }

        public static bool FilesContentsAreEqual(FileInfo fileInfo1, FileInfo fileInfo2)
        {
            if (fileInfo1 == null)
            {
                throw new ArgumentNullException(nameof(fileInfo1));
            }

            if (fileInfo2 == null)
            {
                throw new ArgumentNullException(nameof(fileInfo2));
            }

            if (string.Equals(fileInfo1.FullName, fileInfo2.FullName, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }

            if (fileInfo1.Length != fileInfo2.Length)
            {
                return false;
            }
            else
            {
                using (var file1 = fileInfo1.OpenRead())
                {
                    using (var file2 = fileInfo2.OpenRead())
                    {
                        return StreamsContentsAreEqual(file1, file2);
                    }
                }
            }
        }

        private static int ReadFullBuffer(Stream stream, byte[] buffer)
        {
            int bytesRead = 0;
            while (bytesRead < buffer.Length)
            {
                int read = stream.Read(buffer, bytesRead, buffer.Length - bytesRead);
                if (read == 0)
                {
                    // Reached end of stream.
                    return bytesRead;
                }

                bytesRead += read;
            }

            return bytesRead;
        }

        private static bool StreamsContentsAreEqual(Stream stream1, Stream stream2)
        {
            const int bufferSize = 1024 * sizeof(Int64);
            var buffer1 = new byte[bufferSize];
            var buffer2 = new byte[bufferSize];

            while (true)
            {
                int count1 = ReadFullBuffer(stream1, buffer1);
                int count2 = ReadFullBuffer(stream2, buffer2);

                if (count1 != count2)
                {
                    return false;
                }

                if (count1 == 0)
                {
                    return true;
                }

                int iterations = (int)Math.Ceiling((double)count1 / sizeof(Int64));
                for (int i = 0; i < iterations; i++)
                {
                    if (BitConverter.ToInt64(buffer1, i * sizeof(Int64)) != BitConverter.ToInt64(buffer2, i * sizeof(Int64)))
                    {
                        return false;
                    }
                }
            }
        }
    }
}

或者如果你想成为超级棒,你可以使用异步变体:

using System;
using System.IO;
using System.Threading.Tasks;

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            var fi1 = new FileInfo(args[0]);
            var fi2 = new FileInfo(args[1]);
            Console.WriteLine(FilesContentsAreEqualAsync(fi1, fi2).GetAwaiter().GetResult());
        }

        public static async Task<bool> FilesContentsAreEqualAsync(FileInfo fileInfo1, FileInfo fileInfo2)
        {
            if (fileInfo1 == null)
            {
                throw new ArgumentNullException(nameof(fileInfo1));
            }

            if (fileInfo2 == null)
            {
                throw new ArgumentNullException(nameof(fileInfo2));
            }

            if (string.Equals(fileInfo1.FullName, fileInfo2.FullName, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }

            if (fileInfo1.Length != fileInfo2.Length)
            {
                return false;
            }
            else
            {
                using (var file1 = fileInfo1.OpenRead())
                {
                    using (var file2 = fileInfo2.OpenRead())
                    {
                        return await StreamsContentsAreEqualAsync(file1, file2).ConfigureAwait(false);
                    }
                }
            }
        }

        private static async Task<int> ReadFullBufferAsync(Stream stream, byte[] buffer)
        {
            int bytesRead = 0;
            while (bytesRead < buffer.Length)
            {
                int read = await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead).ConfigureAwait(false);
                if (read == 0)
                {
                    // Reached end of stream.
                    return bytesRead;
                }

                bytesRead += read;
            }

            return bytesRead;
        }

        private static async Task<bool> StreamsContentsAreEqualAsync(Stream stream1, Stream stream2)
        {
            const int bufferSize = 1024 * sizeof(Int64);
            var buffer1 = new byte[bufferSize];
            var buffer2 = new byte[bufferSize];

            while (true)
            {
                int count1 = await ReadFullBufferAsync(stream1, buffer1).ConfigureAwait(false);
                int count2 = await ReadFullBufferAsync(stream2, buffer2).ConfigureAwait(false);

                if (count1 != count2)
                {
                    return false;
                }

                if (count1 == 0)
                {
                    return true;
                }

                int iterations = (int)Math.Ceiling((double)count1 / sizeof(Int64));
                for (int i = 0; i < iterations; i++)
                {
                    if (BitConverter.ToInt64(buffer1, i * sizeof(Int64)) != BitConverter.ToInt64(buffer2, i * sizeof(Int64)))
                    {
                        return false;
                    }
                }
            }
        }
    }
}

1
投票

如果文件不是太大,您可以使用:

public static byte[] ComputeFileHash(string fileName)
{
    using (var stream = File.OpenRead(fileName))
        return System.Security.Cryptography.MD5.Create().ComputeHash(stream);
}

如果散列对存储很有用,那么比较散列是可行的。

(编写了更清洁的代码。)


1
投票

对长度相同的大文件的另一个改进可能是不按顺序读取文件,而是比较或多或少的随机块。

您可以使用多个线程,从文件中的不同位置开始并向前或向后比较。

这样,您可以检测文件中间/末尾的更改,比使用顺序方法更快地检测到更改。


1
投票

如果你只需要比较两个文件,我想最快的方法是(在C中,我不知道它是否适用于.NET)

  1. 打开文件f1,f2
  2. 获取相应的文件长度l1,l2
  3. 如果l1!= l2,则文件不同;停
  4. mmap()两个文件
  5. 在mmap()ed文件上使用memcmp()

OTOH,如果你需要查找一组N个文件中是否有重复文件,那么最快的方法无疑是使用散列来避免N路逐位比较。


1
投票

某些东西(希望)合理有效:

public class FileCompare
{
    public static bool FilesEqual(string fileName1, string fileName2)
    {
        return FilesEqual(new FileInfo(fileName1), new FileInfo(fileName2));
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="file1"></param>
    /// <param name="file2"></param>
    /// <param name="bufferSize">8kb seemed like a good default</param>
    /// <returns></returns>
    public static bool FilesEqual(FileInfo file1, FileInfo file2, int bufferSize = 8192)
    {
        if (!file1.Exists || !file2.Exists || file1.Length != file2.Length) return false;

        var buffer1 = new byte[bufferSize];
        var buffer2 = new byte[bufferSize];

        using (var stream1 = file1.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            using (var stream2 = file2.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
            {

                while (true)
                {
                    var bytesRead1 = stream1.Read(buffer1, 0, bufferSize);
                    var bytesRead2 = stream2.Read(buffer2, 0, bufferSize);

                    if (bytesRead1 != bytesRead2) return false;
                    if (bytesRead1 == 0) return true;
                    if (!ArraysEqual(buffer1, buffer2, bytesRead1)) return false;
                }
            }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="array1"></param>
    /// <param name="array2"></param>
    /// <param name="bytesToCompare"> 0 means compare entire arrays</param>
    /// <returns></returns>
    public static bool ArraysEqual(byte[] array1, byte[] array2, int bytesToCompare = 0)
    {
        if (array1.Length != array2.Length) return false;

        var length = (bytesToCompare == 0) ? array1.Length : bytesToCompare;
        var tailIdx = length - length % sizeof(Int64);

        //check in 8 byte chunks
        for (var i = 0; i < tailIdx; i += sizeof(Int64))
        {
            if (BitConverter.ToInt64(array1, i) != BitConverter.ToInt64(array2, i)) return false;
        }

        //check the remainder of the array, always shorter than 8 bytes
        for (var i = tailIdx; i < length; i++)
        {
            if (array1[i] != array2[i]) return false;
        }

        return true;
    }
}

1
投票

以下是一些实用程序函数,可用于确定两个文件(或两个流)是否包含相同的数据。

我提供了一个多线程的“快速”版本,因为它使用Tasks比较不同线程中的字节数组(每个缓冲区中已读取的每个缓冲区)。

正如预期的那样,它更快(大约快3倍)但它消耗更多的CPU(因为它是多线程的)和更多的内存(因为它需要每个比较线程两个字节的数组缓冲区)。

    public static bool AreFilesIdenticalFast(string path1, string path2)
    {
        return AreFilesIdentical(path1, path2, AreStreamsIdenticalFast);
    }

    public static bool AreFilesIdentical(string path1, string path2)
    {
        return AreFilesIdentical(path1, path2, AreStreamsIdentical);
    }

    public static bool AreFilesIdentical(string path1, string path2, Func<Stream, Stream, bool> areStreamsIdentical)
    {
        if (path1 == null)
            throw new ArgumentNullException(nameof(path1));

        if (path2 == null)
            throw new ArgumentNullException(nameof(path2));

        if (areStreamsIdentical == null)
            throw new ArgumentNullException(nameof(path2));

        if (!File.Exists(path1) || !File.Exists(path2))
            return false;

        using (var thisFile = new FileStream(path1, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            using (var valueFile = new FileStream(path2, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                if (valueFile.Length != thisFile.Length)
                    return false;

                if (!areStreamsIdentical(thisFile, valueFile))
                    return false;
            }
        }
        return true;
    }

    public static bool AreStreamsIdenticalFast(Stream stream1, Stream stream2)
    {
        if (stream1 == null)
            throw new ArgumentNullException(nameof(stream1));

        if (stream2 == null)
            throw new ArgumentNullException(nameof(stream2));

        const int bufsize = 80000; // 80000 is below LOH (85000)

        var tasks = new List<Task<bool>>();
        do
        {
            // consumes more memory (two buffers for each tasks)
            var buffer1 = new byte[bufsize];
            var buffer2 = new byte[bufsize];

            int read1 = stream1.Read(buffer1, 0, buffer1.Length);
            if (read1 == 0)
            {
                int read3 = stream2.Read(buffer2, 0, 1);
                if (read3 != 0) // not eof
                    return false;

                break;
            }

            // both stream read could return different counts
            int read2 = 0;
            do
            {
                int read3 = stream2.Read(buffer2, read2, read1 - read2);
                if (read3 == 0)
                    return false;

                read2 += read3;
            }
            while (read2 < read1);

            // consumes more cpu
            var task = Task.Run(() =>
            {
                return IsSame(buffer1, buffer2);
            });
            tasks.Add(task);
        }
        while (true);

        Task.WaitAll(tasks.ToArray());
        return !tasks.Any(t => !t.Result);
    }

    public static bool AreStreamsIdentical(Stream stream1, Stream stream2)
    {
        if (stream1 == null)
            throw new ArgumentNullException(nameof(stream1));

        if (stream2 == null)
            throw new ArgumentNullException(nameof(stream2));

        const int bufsize = 80000; // 80000 is below LOH (85000)
        var buffer1 = new byte[bufsize];
        var buffer2 = new byte[bufsize];

        var tasks = new List<Task<bool>>();
        do
        {
            int read1 = stream1.Read(buffer1, 0, buffer1.Length);
            if (read1 == 0)
                return stream2.Read(buffer2, 0, 1) == 0; // check not eof

            // both stream read could return different counts
            int read2 = 0;
            do
            {
                int read3 = stream2.Read(buffer2, read2, read1 - read2);
                if (read3 == 0)
                    return false;

                read2 += read3;
            }
            while (read2 < read1);

            if (!IsSame(buffer1, buffer2))
                return false;
        }
        while (true);
    }

    public static bool IsSame(byte[] bytes1, byte[] bytes2)
    {
        if (bytes1 == null)
            throw new ArgumentNullException(nameof(bytes1));

        if (bytes2 == null)
            throw new ArgumentNullException(nameof(bytes2));

        if (bytes1.Length != bytes2.Length)
            return false;

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

0
投票

我认为有些应用程序“哈希”比逐字节比较快。如果您需要将文件与其他人进行比较,或者拥有可以更改的照片缩略图。这取决于它在哪里以及如何使用。

private bool CompareFilesByte(string file1, string file2)
{
    using (var fs1 = new FileStream(file1, FileMode.Open))
    using (var fs2 = new FileStream(file2, FileMode.Open))
    {
        if (fs1.Length != fs2.Length) return false;
        int b1, b2;
        do
        {
            b1 = fs1.ReadByte();
            b2 = fs2.ReadByte();
            if (b1 != b2 || b1 < 0) return false;
        }
        while (b1 >= 0);
    }
    return true;
}

private string HashFile(string file)
{
    using (var fs = new FileStream(file, FileMode.Open))
    using (var reader = new BinaryReader(fs))
    {
        var hash = new SHA512CryptoServiceProvider();
        hash.ComputeHash(reader.ReadBytes((int)file.Length));
        return Convert.ToBase64String(hash.Hash);
    }
}

private bool CompareFilesWithHash(string file1, string file2)
{
    var str1 = HashFile(file1);
    var str2 = HashFile(file2);
    return str1 == str2;
}

在这里,你可以得到最快的。

var sw = new Stopwatch();
sw.Start();
var compare1 = CompareFilesWithHash(receiveLogPath, logPath);
sw.Stop();
Debug.WriteLine(string.Format("Compare using Hash {0}", sw.ElapsedTicks));
sw.Reset();
sw.Start();
var compare2 = CompareFilesByte(receiveLogPath, logPath);
sw.Stop();
Debug.WriteLine(string.Format("Compare byte-byte {0}", sw.ElapsedTicks));

或者,我们可以将哈希值保存在数据库中。

希望这可以提供帮助


0
投票

另一个答案来自@chsh。 MD5与文件相同的使用和快捷方式,文件不存在和不同的长度:

/// <summary>
/// Performs an md5 on the content of both files and returns true if
/// they match
/// </summary>
/// <param name="file1">first file</param>
/// <param name="file2">second file</param>
/// <returns>true if the contents of the two files is the same, false otherwise</returns>
public static bool IsSameContent(string file1, string file2)
{
    if (file1 == file2)
        return true;

    FileInfo file1Info = new FileInfo(file1);
    FileInfo file2Info = new FileInfo(file2);

    if (!file1Info.Exists && !file2Info.Exists)
       return true;
    if (!file1Info.Exists && file2Info.Exists)
        return false;
    if (file1Info.Exists && !file2Info.Exists)
        return false;
    if (file1Info.Length != file2Info.Length)
        return false;

    using (FileStream file1Stream = file1Info.OpenRead())
    using (FileStream file2Stream = file2Info.OpenRead())
    { 
        byte[] firstHash = MD5.Create().ComputeHash(file1Stream);
        byte[] secondHash = MD5.Create().ComputeHash(file2Stream);
        for (int i = 0; i < firstHash.Length; i++)
        {
            if (i>=secondHash.Length||firstHash[i] != secondHash[i])
                return false;
        }
        return true;
    }
}

-1
投票

我发现这很好地比较了第一个长度而没有读取数据然后比较读取的字节序列

private static bool IsFileIdentical(string a, string b)
{            
   if (new FileInfo(a).Length != new FileInfo(b).Length) return false;
   return (File.ReadAllBytes(a).SequenceEqual(File.ReadAllBytes(b)));
}

121
投票

最慢的方法是逐字节比较两个文件。我能够提出的最快速度是类似的比较,但是你不是一次只使用一个字节,而是使用一个大小为Int64的字节数组,然后比较得到的数字。

这是我想出的:

    const int BYTES_TO_READ = sizeof(Int64);

    static bool FilesAreEqual(FileInfo first, FileInfo second)
    {
        if (first.Length != second.Length)
            return false;

        if (string.Equals(first.FullName, second.FullName, StringComparison.OrdinalIgnoreCase))
            return true;

        int iterations = (int)Math.Ceiling((double)first.Length / BYTES_TO_READ);

        using (FileStream fs1 = first.OpenRead())
        using (FileStream fs2 = second.OpenRead())
        {
            byte[] one = new byte[BYTES_TO_READ];
            byte[] two = new byte[BYTES_TO_READ];

            for (int i = 0; i < iterations; i++)
            {
                 fs1.Read(one, 0, BYTES_TO_READ);
                 fs2.Read(two, 0, BYTES_TO_READ);

                if (BitConverter.ToInt64(one,0) != BitConverter.ToInt64(two,0))
                    return false;
            }
        }

        return true;
    }

在我的测试中,我能够看到这个表现优于简单的ReadByte()场景几乎3:1。平均超过1000次运行,我在1063ms获得此方法,并且在3031ms处获得下面的方法(直接逐字节比较)。哈希总是在平均865毫秒左右回到亚秒级。这个测试是一个~100MB的视频文件。

这是我使用的ReadByte和散列方法,用于比较目的:

    static bool FilesAreEqual_OneByte(FileInfo first, FileInfo second)
    {
        if (first.Length != second.Length)
            return false;

        if (string.Equals(first.FullName, second.FullName, StringComparison.OrdinalIgnoreCase))
            return true;

        using (FileStream fs1 = first.OpenRead())
        using (FileStream fs2 = second.OpenRead())
        {
            for (int i = 0; i < first.Length; i++)
            {
                if (fs1.ReadByte() != fs2.ReadByte())
                    return false;
            }
        }

        return true;
    }

    static 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;
    }

36
投票

如果您确定需要进行完整的逐字节比较(请参阅其他答案以讨论散列),那么单行解决方案是:

bool filesAreEqual = File.ReadAllBytes(path1).SequenceEqual(File.ReadAllBytes(path2));

与其他一些发布的答案不同,这适用于任何类型的文件:二进制文本,文本,媒体,可执行文件等,但作为完整的二进制比较,文件只有“不重要”的方式不同(例如BOMline-endingcharacter encoding,媒体元数据,空格,填充,源代码注释等)将始终被视为不相等。

此代码完全将两个文件加载到内存中,因此不应将其用于比较巨大的文件。除了这种考虑之外,满载并不是真正的惩罚;实际上,这可能是文件大小的最佳.NET解决方案,预计文件大小将小于85K,因为.NET中的小分配非常便宜,并且上面的代码最大程度地将文件性能和优化委托给CLR / BCL

此外,对于这样的工作日场景,关于通过LINQ枚举器进行逐字节比较(如此处所示)的性能的问题没有实际意义,因为根据文件I / O完全击中磁盘将使数量级的数量相形见绌,各种内存比较替代方案的好处。例如,尽管SequenceEqual实际上确实给了我们放弃第一次不匹配的“优化”,但在获取文件的内容之后这几乎不重要,每次都需要确认匹配。

另一方面,上述代码不包括针对不同大小的文件的急切中止,这可以提供有形(可能可测量的)性能差异。这个是有形的,因为虽然文件长度在WIN32_FILE_ATTRIBUTE_DATA结构中是可用的(无论如何都必须首先获取任何文件访问),继续访问文件的内容需要完全不同的提取,这可能是可能避免的。如果您对此感到担心,解决方案将变为两行:

// slight optimization over the code shown above
bool filesAreEqual = new FileInfo(path1).Length == new FileInfo(path2).Length && 
       File.ReadAllBytes(path1).SequenceEqual(File.ReadAllBytes(path2));

如果(等效的)Length值都被发现为零(未显示)和/或避免构建每个FileInfo两次(也未示出),您也可以扩展这个以避免二次提取。


33
投票

除了Reed Copsey的回答:

  • 最糟糕的情况是两个文件完全相同。在这种情况下,最好逐个字节地比较文件。
  • 如果这两个文件不相同,你可以通过更快地检测到它们不相同来加快速度。

例如,如果两个文件的长度不同,那么您就知道它们不能完全相同,甚至不必比较它们的实际内容。


15
投票

如果你不读取小的8字节块但是放一个循环,读取更大的块,它会变得更快。我将平均比较时间缩短到1/4。

    public static bool FilesContentsAreEqual(FileInfo fileInfo1, FileInfo fileInfo2)
    {
        bool result;

        if (fileInfo1.Length != fileInfo2.Length)
        {
            result = false;
        }
        else
        {
            using (var file1 = fileInfo1.OpenRead())
            {
                using (var file2 = fileInfo2.OpenRead())
                {
                    result = StreamsContentsAreEqual(file1, file2);
                }
            }
        }

        return result;
    }

    private static bool StreamsContentsAreEqual(Stream stream1, Stream stream2)
    {
        const int bufferSize = 1024 * sizeof(Int64);
        var buffer1 = new byte[bufferSize];
        var buffer2 = new byte[bufferSize];

        while (true)
        {
            int count1 = stream1.Read(buffer1, 0, bufferSize);
            int count2 = stream2.Read(buffer2, 0, bufferSize);

            if (count1 != count2)
            {
                return false;
            }

            if (count1 == 0)
            {
                return true;
            }

            int iterations = (int)Math.Ceiling((double)count1 / sizeof(Int64));
            for (int i = 0; i < iterations; i++)
            {
                if (BitConverter.ToInt64(buffer1, i * sizeof(Int64)) != BitConverter.ToInt64(buffer2, i * sizeof(Int64)))
                {
                    return false;
                }
            }
        }
    }
}

15
投票

唯一可能使校验和比较比逐字节比较快一点的事实是你一次读取一个文件,这有点减少磁盘头的查找时间。然而,通过计算散列的额外时间可以很好地消除这种微小的增益。

此外,校验和比较当然只有在文件相同时才有可能更快。如果不是这样,逐字节比较将以第一个差异结束,使其快得多。

您还应该考虑哈希码比较仅告诉您文件很可能是相同的。要100%确定,您需要进行逐字节比较。

例如,如果哈希码是32位,那么如果哈希码匹配,则大约99.99999998%确定文件是相同的。这接近100%,但如果你真的需要100%的确定性,那不是它。


11
投票

编辑:此方法不适用于比较二进制文件!

在.NET 4.0中,File类具有以下两种新方法:

public static IEnumerable<string> ReadLines(string path)
public static IEnumerable<string> ReadLines(string path, Encoding encoding)

这意味着您可以使用:

bool same = File.ReadLines(path1).SequenceEqual(File.ReadLines(path2));

6
投票

老实说,我认为你需要尽可能地修剪你的搜索树。

在逐字节前进行检查:

  1. 尺寸是否相同?
  2. 文件A中的最后一个字节是否与文件B不同

此外,由于驱动器更快地读取顺序字节,因此一次读取大块将更有效。逐字节转换不仅会导致更多的系统调用,而且如果两个文件位于同一驱动器上,它会导致传统硬盘驱动器的读取头更频繁地来回查找。

将块A和块B读入字节缓冲区,并进行比较(不要使用Array.Equals,请参阅注释)。调整块的大小,直到达到你认为在内存和性能之间的良好折衷。您也可以多线程比较,但不要多线程磁盘读取。


2
投票

我的实验表明,调用Stream.ReadByte()的次数肯定会有所帮助,但使用BitConverter封装字节对于比较字节数组中的字节没有多大区别。

因此,可以用上面最简单的注释替换上面注释中的“Math.Ceiling和iterations”循环:

            for (int i = 0; i < count1; i++)
            {
                if (buffer1[i] != buffer2[i])
                    return false;
            }

我想这与BitConverter.ToInt64在比较之前需要做一些工作(检查参数然后执行位移)的事实有关,并且最终与两个数组中的8个字节的比较工作量相同。

© www.soinside.com 2019 - 2024. All rights reserved.