c# - quédate - ¿Cómo hash un solo archivo de varias maneras al mismo tiempo?
ha*ash quédate lejos (3)
Estás todo el camino hasta allí, simplemente no necesitas leer todo en la memoria de una vez.
Todos los hashes en .Net derivan de la clase HashAlgorithm . Esto tiene dos métodos: TransformBlock
y TransformFinalBlock
. Por lo tanto, debería poder leer un fragmento para su archivo, rellenarlo con el método TransformBlock de los hashes que quiera usar y luego pasar al siguiente bloque. Solo recuerde llamar a TransformFinalBlock
para obtener su último fragmento del archivo, ya que eso es lo que le proporciona la matriz de bytes que contiene el hash.
Por ahora, solo haría cada hash de a uno por vez, hasta que esté funcionando, y luego me preocuparé por ejecutar los hash al mismo tiempo (utilizando algo así como la Biblioteca de tareas paralelas)
Estoy intentando diseñar una aplicación simple para el cálculo de un archivo CRC32 / md5 / sha1 / sha256 / sha384 / sha512, y me he topado con un obstáculo. Esto se está haciendo en C #.
Me gustaría poder hacer esto de la manera más eficiente posible, así que mi idea original fue leer el archivo en una secuencia de memoria antes de procesar, pero pronto descubrí que los archivos muy grandes me hacían perder memoria muy rápidamente. Entonces parece que tengo que usar un filestream en su lugar. El problema, según lo veo, es que solo se puede ejecutar una función hash a la vez, y hacerlo con una cadena de archivos tardará un tiempo en completarse.
¿Cómo puedo leer un pequeño bit de un archivo en la memoria, procesarlo con los 6 algoritmos y luego ir a otro pedazo ... o el hashing no funciona de esa manera?
Este fue mi intento original de leer un archivo en la memoria. Falló cuando traté de leer una imagen de CD en la memoria antes de ejecutar los algoritmos de hash en el flujo de memoria:
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;
}
}
}
Esta podría ser una gran oportunidad para mojarse los pies con los objetos de flujo de datos de TPL. Lea el archivo en un hilo y publique los datos en un BroadcastBlock<T>
. BroadcastBlock<T>
se vinculará a 6 ActionBlock<T>
diferentes de ActionBlock<T>
. Cada ActionBlock<T>
corresponderá a una de tus 6 estrategias hash.
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>
reenviará cada fragmento de datos a todas las ActionBlock<T>
vinculadas de ActionBlock<T>
.
Dado que su pregunta se centró más en cómo lograr que todo esto ocurra al mismo tiempo, le dejaré la implementación de DoHash
.
private void DoHash(byte[] input, HashAlgorithm algorithm)
{
// You will need to implement this.
}
Los algoritmos hash están diseñados de forma que puede calcular el valor hash de forma incremental. Aquí puede encontrar un ejemplo de C # /. NET. Puede modificar fácilmente el código proporcionado para actualizar múltiples instancias de algoritmo hash en cada paso.