【问题标题】:C# MD5 hasher exampleC# MD5 哈希器示例
【发布时间】:2009-05-06 00:24:01
【问题描述】:

编辑:我已将其重命名为示例,因为代码按预期工作。

我正在尝试复制一个文件,获取一个 MD5 哈希,然后删除该副本。我这样做是为了避免另一个应用程序写入的原始文件的进程锁定。但是,我正在锁定我已复制的文件。

File.Copy(pathSrc, pathDest, true);

String md5Result;
StringBuilder sb = new StringBuilder();
MD5 md5Hasher = MD5.Create();

using (FileStream fs = File.OpenRead(pathDest))
{
    foreach(Byte b in md5Hasher.ComputeHash(fs))
        sb.Append(b.ToString("x2").ToLower());
}

md5Result = sb.ToString();

File.Delete(pathDest);

然后我在File.Delete() 上收到“进程无法访问文件”异常。

我希望使用using 语句,文件流会很好地关闭。我也尝试过单独声明文件流,删除using,并在读取后放置fs.Close()fs.Dispose()

在这之后,我把实际的md5计算注释掉了,代码执行了,文件被删除了,所以看起来和ComputeHash(fs)有关。

【问题讨论】:

  • 你为什么不直接调用 ReadAllBytes() 并完成它?
  • 因为他对 computeHash 的调用是在流上运行的——如果文件很大,他就不需要把它全部保存在内存中。
  • 删除前不需要关闭文件吗?

标签: c# hash md5


【解决方案1】:

导入命名空间

using System.Security.Cryptography;

这是返回 md5 哈希码的函数。您需要将字符串作为参数传递。

public static string GetMd5Hash(string input)
{
        MD5 md5Hash = MD5.Create();
        // Convert the input string to a byte array and compute the hash.
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

        // Create a new Stringbuilder to collect the bytes
        // and create a string.
        StringBuilder sBuilder = new StringBuilder();

        // Loop through each byte of the hashed data 
        // and format each one as a hexadecimal string.
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

        // Return the hexadecimal string.
        return sBuilder.ToString();
}

【讨论】:

    【解决方案2】:

    我把你的代码放在控制台应用程序中并运行它没有错误,得到哈希并且测试文件在执行结束时被删除?我只是使用了我的测试应用程序中的 .pdb 作为文件。

    您运行的是什么版本的 .NET?

    我将我拥有的代码放在这里,如果你把它放在 VS2008 .NET 3.5 sp1 的控制台应用程序中,它运行没有错误(至少对我来说)。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Cryptography;
    using System.IO;
    
    namespace lockTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                string hash = GetHash("lockTest.pdb");
    
                Console.WriteLine("Hash: {0}", hash);
    
                Console.ReadKey();
            }
    
            public static string GetHash(string pathSrc)
            {
                string pathDest = "copy_" + pathSrc;
    
                File.Copy(pathSrc, pathDest, true);
    
                String md5Result;
                StringBuilder sb = new StringBuilder();
                MD5 md5Hasher = MD5.Create();
    
                using (FileStream fs = File.OpenRead(pathDest))
                {
                    foreach (Byte b in md5Hasher.ComputeHash(fs))
                        sb.Append(b.ToString("x2").ToLower());
                }
    
                md5Result = sb.ToString();
    
                File.Delete(pathDest);
    
                return md5Result;
            }
        }
    }
    

    【讨论】:

    • 代码确实有效,我是 n00b。我在锁定文件的 MD5hash 之后重用了文件。
    • 什么是坏主意?我帮助他弄清楚为什么代码不起作用。复制一个大文件以防止它被锁定并不是世界末日。你到底在说什么我对他的回答是错误的,他的代码确实有效并创建了一个示例来说明它? @amin,您能否提供更多背景信息?
    【解决方案3】:

    您是否也尝试将 MD5 对象包装在 using() 中?从文档中,MD5 是一次性的。这可能会让它放弃文件。

    【讨论】:

    • 是的,你可能想要抽象一个函数,它接受一个文件名并返回一个哈希字符串。
    【解决方案4】:

    md5hasher.Clear() 在你的循环之后可能会成功。

    【讨论】:

      【解决方案5】:

      您是否尝试在删除文件之前将 md5Hasher 设置为 null?它可能还有一个句柄仍附加到 FileStream(可能是内存泄漏)。

      【讨论】:

      • 将变量设置为 null 不会立即影响它是否仍在内存中并仍然持有某些资源。垃圾收集器及其终结器极不可能在设置将变量设置为 null 的代码和随后的代码行之间介入。事实上,编译器很可能会忽略将变量设置为 null 的行。它肯定不会触发处置、垃圾收集或终结。
      【解决方案6】:

      为什么不用 FileShare.ReadWrite 打开文件?

      【讨论】:

        猜你喜欢
        • 2020-12-08
        • 1970-01-01
        • 1970-01-01
        • 2014-05-19
        • 2019-10-10
        • 2015-07-07
        • 2012-08-17
        • 1970-01-01
        相关资源
        最近更新 更多