12

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

我正在尝试复制文件,获取 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).

4

6 回答 6

20

导入名称空间

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();
}
于 2012-12-10T17:39:55.143 回答
15

我把你的代码放在一个控制台应用程序中并没有错误地运行它,得到了哈希并且测试文件在执行结束时被删除了?我只是使用我的测试应用程序中的 .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;
        }
    }
}
于 2009-05-06T01:54:22.433 回答
1

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

于 2009-05-06T00:28:28.443 回答
0

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

于 2009-05-06T01:38:52.110 回答
-1

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

于 2009-05-06T00:31:13.897 回答
-1

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

于 2009-05-06T01:06:00.800 回答