我正在尝试设计一个简单的应用程序用于计算文件的CRC32 / md5 / sha1 / sha256 / sha384 / sha512,我遇到了一些障碍。这是在C#中完成的。
我希望能够尽可能高效地完成这项工作,所以我最初的想法是在处理之前首先将文件读入内存流,但我很快发现非常大的文件导致我的内存耗尽很快。所以我似乎必须使用文件流。我认为问题在于,一次只能运行一个哈希函数,使用文件流执行此操作需要一段时间才能完成每个哈希。
我怎样才能将一小段文件读入内存,使用所有6种算法处理它,然后转到另一块...或者哈希不能以这种方式工作?
这是我原本尝试将文件读入内存。当我在内存流上运行散列算法之前尝试将CD映像读入内存时,它失败了:
private void ReadToEndOfFile(string filename)
{
if (File.Exists(filename))
{
FileInfo fi = new FileInfo(filename);
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[16 * 1024];
//double step = Math.Floor((double)fi.Length / (double)100);
this.toolStripStatusLabel1.Text = "Reading File...";
this.toolStripProgressBar1.Maximum = (int)(fs.Length / buffer.Length);
this.toolStripProgressBar1.Value = 0;
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
this.toolStripProgressBar1.Value += 1;
}
_ms = ms;
}
}
}
答案 0 :(得分:4)
哈希算法的设计方式是您可以递增地计算哈希值。您可以找到here的C#/ .NET示例。您可以轻松修改提供的代码,以在每个步骤中更新多个哈希算法实例。
答案 1 :(得分:3)
你大部分时间都在那里,你不需要立即将整个内容读入内存。
.Net中的所有哈希值都来自HashAlgorithm类。这有两种方法:TransformBlock
和TransformFinalBlock
。因此,您应该能够读取文件的块,将其填入您想要使用的任何哈希的TransformBlock方法中,然后移动到下一个块中。只需记住从文件中调用TransformFinalBlock
作为最后一个块,因为这样就可以获得包含哈希的字节数组。
现在,我一次只做一个哈希,直到它工作,然后担心同时运行哈希(使用类似任务并行库的东西)
答案 2 :(得分:-1)
这可能是让您了解TPL数据流对象的绝佳机会。在一个线程中读取文件并将数据发布到BroadcastBlock<T>
。 BroadcastBlock<T>
将链接到6个不同的ActionBlock<T>
个实例。每个ActionBlock<T>
将对应您的6个哈希策略之一。
var broadcast = new BroadcastBlock<byte[]>(x => x);
var strategy1 = new ActionBlock<byte[]>(input => DoHash(input, SHA1.Create()));
var strategy2 = new ActionBlock<byte[]>(input => DoHash(input, MD5.Create()));
// Create the other 4 strategies.
broadcast.LinkTo(strategy1);
broadcast.LinkTo(strategy2);
// Link the other 4.
using (var fs = File.Open(@"yourfile.txt", FileMode.Open, FileAccess.Read))
using (var br = new BinaryReader(fs))
{
while (br.PeekChar() != -1)
{
broadcast.Post(br.ReadBytes(1024 * 16));
}
}
BroadcastBlock<T>
会将每个数据块转发到所有链接的ActionBlock<T>
实例。
由于您的问题更多地集中于如何让所有这一切同时发生,因此我会将DoHash
的实施留给您。
private void DoHash(byte[] input, HashAlgorithm algorithm)
{
// You will need to implement this.
}