65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 MD5 哈希的 IEqualityComparer<FileInfo>

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2018 年 5 月 25 日

CPOL

1分钟阅读

viewsIcon

13542

此代码片段使用 IEqualityComparer 比较两个给定的文件。

引言

此代码片段使用 IEqualityComparer 比较两个给定的文件。

比较过程如下:

- 使用 FileInfo 的相等运算符 (==) 尝试确定它们是否是 FileInfo 类的相同实例
- 如果其中一个对象为 null,则它们不能代表相同的文件,因此返回 false
- 如果两个对象的的文件路径相同,则返回 true,因为文件必须相同
- 如果文件大小不同,则文件也不能相同,因此返回 false
- 最后,我们采用比较两个文件的 MD5 哈希值。

请记住,MD5 哈希是一种代价较高的操作,不适合比较大量文件或大型文件。 此处提供的代码最初打算在集成测试中使用。 如果需要比较大量文件(或非常大的文件),您可以使用自己的实现 - 您可以从阅读 此 Stack Overflow 讨论 开始。

背景

请记住,此实现会将文件内容读取到内存中以创建每个文件的 MD5。 如果您尝试比较非常大的文件,这可能会大大降低应用程序的速度。

代码

/// <summary>
/// An <see cref="IEqualityComparer{T}"/> for files using <see cref="FileInfo"/>
/// </summary>
public class FileMd5EqualityComparer : IEqualityComparer<FileInfo>
{
    /// <summary>
    /// See <see cref="IEqualityComparer{T}.Equals(T, T)"/>
    /// </summary>
    public bool Equals(FileInfo x, FileInfo y)
    {
        // Use basic comparison
        if(x == y)
        {
            return true;
        }

        // if one of both parameters is null, they can't be
        // the same - Except both are null, but this case is
        // handled above.
        if(x == null || y == null)
        {
            return false;
        }

        // If both file paths are the same, the
        // files must be the same.
        if(x.FullName == y.FullName)
        {
            return true;
        }

        // The files can't be equal if they don't
        // have the same size
        if(x.Length != y.Length)
        {
            return false;
        }

        // At last, compare the MD5 of the files.
        var md5X = GetMd5(x.FullName);
        var md5Y = GetMd5(y.FullName);

        return md5X == md5Y;
    }

    /// <summary>
    /// See <see cref="IEqualityComparer{T}.Equals(T, T)"/>
    /// </summary>
    public int GetHashCode(FileInfo obj)
    {
        return obj.GetHashCode();
    }

    /// <summary>
    /// Returns the MD5 of the file at <paramref name="filePath"/>
    /// as string
    /// </summary>
    private string GetMd5(string filePath)
    {
        using (var md5 = MD5.Create())
        {
            using (var stream = File.OpenRead(filePath))
            {
                return Encoding.Default.GetString(md5.ComputeHash(stream));
            }
        }
    }
}

历史

2018-05-25 初始版本

© . All rights reserved.