C#-为文件和子目录中的文件创建MD5哈希并将其写入文本文件

时间:2018-10-27 00:07:32

标签: c#

我正在尝试编写一个简单的Windows控制台应用程序,该应用程序将执行以下操作:

为给定文件夹中的每个文件创建一个MD5哈希,并将文件名(包括文件目录)和生成的哈希写入文本文件。 我能够创建哈希并将带有哈希的文件名写入文本文件。 我无法解决的部分是我在文件名的前面加上目录的情况。

一个例子:

我的根目录是C:\temp

C:\temp中,我有3个文件:

a.txtb.txtc.txt。 此外,C:\temp中有2个文件夹:

001002

001包含其他3个文件,002包含一些文件和另一个目录。

粗略地说,我希望我的输出是:

a.txt 1B2M2Y8AsgTpgAmY7PhCfg2
b.txt 8pilZcutPpW5x6atctbWWQ2
c.txt 7wGB3hjvOVGAbArWO4l7pA2
001\d.txt _Uqz2gB17nv1Vxrh-MPrCw2
001\e.txt 1B2M2Y8AsgTpgAmY7PhCfg2
001\f.txt _Uqz2gB17nv1Vxrh-MPrCw2
002\g.txt 1B2M2Y8AsgTpgAmY7PhCfg2
002\h.txt 7wGB3hjvOVGAbArWO4l7pA2
002\test\i.txt _Uqz2gB17nv1Vxrh-MPrCw2
002\test\j.txt 7wGB3hjvOVGAbArWO4l7pA2

我当前的输出是

a.txt 1B2M2Y8AsgTpgAmY7PhCfg2
b.txt 8pilZcutPpW5x6atctbWWQ2
c.txt 7wGB3hjvOVGAbArWO4l7pA2
d.txt _Uqz2gB17nv1Vxrh-MPrCw2
e.txt 1B2M2Y8AsgTpgAmY7PhCfg2
f.txt _Uqz2gB17nv1Vxrh-MPrCw2
g.txt 1B2M2Y8AsgTpgAmY7PhCfg2
h.txt 7wGB3hjvOVGAbArWO4l7pA2
i.txt _Uqz2gB17nv1Vxrh-MPrCw2
j.txt 7wGB3hjvOVGAbArWO4l7pA2

这是我当前的代码。感谢您提出的任何建议或提示,以使我的代码变得更好。

using System;
using System.Linq;
using System.Security.Cryptography;
using System.IO;
using System.Web;

namespace MD5_Generator
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("MD5 Hash Generator");
            Console.WriteLine("This program creates MD5 hashes for all files in the folder.");
            Console.WriteLine("Work in progress...");
            string root = Directory.GetCurrentDirectory();
            string hashList = root + "/hashList.txt";            
            if (!File.Exists(hashList))
            {
                var initHastListFile = File.Create(hashList);
                initHastListFile.Close();
            }
            else
            {
                File.Delete(hashList);
                var hastListFile = File.Create(hashList);
                hastListFile.Close();
            }
            int i = 0;
            string[] allFiles = Directory.GetFiles(root, "*.*", SearchOption.AllDirectories);
            string[] lines = new string[allFiles.Count()];

            lines = DirSearch(root, lines, i);
            File.AppendAllLines(hashList, lines);

            Console.ReadKey();
        }

        static string[] DirSearch(string dir, string[] lines, int counter)
        {
            string hashListFileName = "hashList.txt";
            foreach (string f in Directory.GetFiles(dir))
            {
                //2. Create an MD5 hash per file
                using (var md5 = MD5.Create())
                {
                    FileInfo info = new FileInfo(f);
                    string filename = info.FullName;
                    if (filename != hashListFileName)
                    {
                        using (var stream = File.OpenRead(filename))
                        {
                            byte[] fileMD5 = md5.ComputeHash(stream);
                            string hash = HttpServerUtility.UrlTokenEncode(fileMD5);
                            string currDir = Path.GetDirectoryName(filename);                         
                            lines[counter] = info.Name + " " + hash;                            
                        }
                        counter++;
                    }
                }
            }

            foreach (string d in Directory.GetDirectories(dir))
            {
                DirSearch(d, lines, counter);
            }

            return lines;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我猜是这样的

方法

public static IEnumerable<(string fileName, string hash)> GetHasList(string path, bool isRelative)
{
   foreach (var file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
   {
      string hash;
      using (var md5 = MD5.Create())
         using (var stream = File.OpenRead(file))
            hash = HttpServerUtility.UrlTokenEncode(md5.ComputeHash(stream));
      if (isRelative)
         yield return (file.Remove(0, path.TrimEnd('/').Length+1), hash);
      else
         yield return (file, hash);
   }
}

用法

string output = Path.Combine(@"D:\", "hashList.txt");

// format results
var data = GetHasList(@"D:\Temp",true).Select(x => $"{x.fileName} {x.hash}");

// write file
File.WriteAllLines(output, data);

如果要使其对空间的容错性更高

// format results
var data = GetHasList(@"D:\Temp",true).Select(x => $"\"{x.fileName}\" {x.hash}");

输出

"2284804723016.xml" UBtEG5qItCVKf8VTdamoCQ2
"2301708833016.xml" vRiXj012Q9RlU9xEgZPjcA2
"New folder\2320158695015.xml" hpDYqQuy_wvQMD5tOMJxjA2
"New folder\2282121972016.xml" j-Y06SdEM3kHjbhTIqhTKg2
"New folder (2)\2281419740016.xml" 3GWrCgtrda-W4ymCNSi4MA2
"New folder (2)\2281593123016.xml" ncqGPehpHflpzjl0j0nFfQ2

答案 1 :(得分:0)

我现在用以下代码实现了

using System;
using System.Linq;
using System.Security.Cryptography;
using System.IO;
using System.Web;

namespace MD5_Generator
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("MD5 Hash Generator");
            Console.WriteLine("This program creates MD5 hashes for all files in the folder.");
            Console.WriteLine("Work in progress...");
            string root = Directory.GetCurrentDirectory();
            string hashList = root + "/hashList.txt";            
            if (!File.Exists(hashList))
            {
                var initHastListFile = File.Create(hashList);
                initHastListFile.Close();
            }
            else
            {
                File.Delete(hashList);
                var hastListFile = File.Create(hashList);
                hastListFile.Close();
            }
            int i = 0;
            string[] allFiles = Directory.GetFiles(root, "*.*", SearchOption.AllDirectories);
            string[] lines = new string[allFiles.Count()];

            lines = DirSearch(root, lines, i, root);
            File.AppendAllLines(hashList, lines);

            Console.ReadKey();

        }

        static string[] DirSearch(string dir, string[] lines, int counter, string root)
        {
            string hashListFileName = "hashList.txt";
            foreach (string f in Directory.GetFiles(dir))
            {
                //2. Create an MD5 hash per file
                using (var md5 = MD5.Create())
                {
                    FileInfo info = new FileInfo(f);
                    string filename = info.FullName;
                    if (filename != hashListFileName)
                    {
                        using (var stream = File.OpenRead(filename))
                        {
                            byte[] fileMD5 = md5.ComputeHash(stream);
                            string hash = HttpServerUtility.UrlTokenEncode(fileMD5);
                            string currDir = Path.GetDirectoryName(filename);                         
                            lines[counter] = info.FullName.Substring(root.Length+1) + " " + hash;                            
                        }
                        counter++;
                    }
                }
            }

            foreach (string d in Directory.GetDirectories(dir))
            {
                DirSearch(d, lines, counter, root);
            }

            return lines;
        }
    }
}

我只是使用Substring方法来“切除” rootDirectory.GetCurrentDirectory();的不相关部分:

lines[counter] = info.FullName.Substring(root.Length+1) + " " + hash;

结果看起来就像我想要的一样!

MD5_Generator.exe NVt6BVhZyy0QQPA-Cumntg2
MD5_Generator.exe.config 7wGB3hjvOVGAbArWO4l7pA2
MD5_Generator.pdb _M_l1ka8Jg_c0LOtbXfF6g2
System.ValueTuple.dll mc7Hfb7gqxC5_E1SodQUvg2
System.ValueTuple.xml So9YKXUqAxilrTjfmxgVPQ2
Test\123.txt 1B2M2Y8AsgTpgAmY7PhCfg2
Test\Test2\dhf9.txt 1B2M2Y8AsgTpgAmY7PhCfg2

感谢您的贡献!