.net 在C#中计算映像的MD5校验和

cygmwpex  于 2023-03-04  发布在  .NET
关注(0)|答案(2)|浏览(107)

StackOverflow题目“Calclate MD5 checksum for a file”中引用的代码提供了一种基于文件获取校验和的简单方法。这是可行的,但是通过测试,我发现更改文件元数据也会导致校验和更改。我想这是有道理的,因为从技术上讲,具有不同元数据的副本是不同的文件。该代码:

using (var md5 = MD5.Create())
{
    using (var stream = File.OpenRead(filename))
    {
        return md5.ComputeHash(stream);
    }
}

当图像在工作中通过各种系统时,图像元数据会因各种原因而添加和更改,这意味着文件校验和不能用于查找系统中的重复项。
我需要的是一种基于映像本身而不是映像 * 文件 * 生成校验和的方法。
我尝试解决此问题,结果生成了以下代码:

using (var md5 = MD5.Create())
{
    using (var stream = new MemoryStream())
    {
        using (Image image = Image.FromFile(fileName))
        {
            image.Save(stream, image.RawFormat);
            var hash = md5.ComputeHash(stream);
            var convertedHash = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant();
            return convertedHash;
        }
                        
    }
}

这对我来说似乎很简单,代码运行没有错误,但是无论我输入什么图像,我都得到相同的校验和,所以有些地方是错的。我只是似乎不能确定为什么会发生这种行为。任何输入或知识都非常感谢。为什么这会为任何图像生成相同的校验和?我做错了什么或遗漏了什么?
(Edit:为了清楚起见,我知道图像数据本身必须完全相同才能生成相同的校验和;这就是我所需要的。iIndiee.,我不想找到相似或非常相似的图像等)

2lpgd968

2lpgd9681#

尝试将流位置重置为起始位置:

stream.Seek(0, SeekOrigin.Begin);

Save()之后和ComputeHash()之前执行此操作。

fafcakar

fafcakar2#

您的问题是由以下事实引起的:在写入流之后,在阅读流之前没有重置流的位置,因此每次都得到相同的哈希值。
您可以通过传入一个新流来轻松验证这一点:

var hash = md5.ComputeHash(new MemoryStream());
var convertedHash = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant();
return convertedHash;

这对我来说返回d41d8cd98f00b204e9800998ecf8427e,与我在加载文件而不倒带流时得到的结果相同。
如果你重置了位置,你会得到每个文件不同的哈希值:

public string GetHashFromImage(string fileName)
{
    using (var md5 = MD5.Create())
    {
        using (var stream = new MemoryStream())
        {
            using (Image image = Image.FromFile(fileName))
            {
                image.Save(stream, image.RawFormat);
                
                stream.Position = 0;
                
                var hash = md5.ComputeHash(stream);
                var convertedHash = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant();
                return convertedHash;
            }

        }
    }
}

相关问题