Tengo un inputStream
que quiero usar para calcular un hash y guardar el archivo en el disco. Me gustaría saber cómo hacerlo de manera eficiente. ¿Debo usar alguna tarea para hacer eso al mismo tiempo, debería duplicar el pase de transmisión a dos flujos, uno para el método saveFile
y otro para el método computeHash
, o debería hacer algo más?¿Computing Hash al guardar un archivo?
Respuesta
Tendrá que rellenar los bytes de la secuencia en un byte[]
para picarlos.
También puede pasar una transmisión. ¿Cuáles serían los beneficios de convertir el flujo a un byte []? – Dave
Yo, por alguna razón, no vi esa sobrecarga. Nunca. Iré a decir 10 "Hail Bills Gates" en penitencia. – bluevector
@Dave No hay ventaja. Tanto el formulario que toma un 'byte []' como un 'Stream' están bloqueando y esperan los datos completos en one-shot. Con hilos y un 'Stream' especial ... pero eso solo agrega más problemas, entonces resuelve ... –
¿Qué pasa con el uso de algoritmos hash que operan en un nivel de bloque? Puede agregar el bloque al hash (usando TransformBlock) y posteriormente escribir el bloque en el bloque foreach del archivo en la secuencia.
No comprobado tiro áspera:
using System.IO;
using System.Security.Cryptography;
...
public byte[] HashedFileWrite(string filename, Stream input)
{
var hash_algorithm = MD5.Create();
using(var file = File.OpenWrite(filename))
{
byte[] buffer = new byte[4096];
int read = 0;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
hash_algorithm.TransformBlock(buffer, 0, read, null, 0);
file.Write(buffer, 0, read);
}
hash_algorithm.TransformFinalBlock(buffer, 0, read);
}
return hash_algorithm.Hash;
}
No soy un gran admirador del procesamiento manual de bloques, pero debería funcionar. (Creo que el CryptoStream es un enfoque más simple que se reduce a ser un envoltorio bonito.) –
De acuerdo. Generalmente los evito como la peste (gracias a Dios por el reciente método Stream.CopyTo) ... Creo que esta es la mejor manera de resolver el problema. Además, una segunda lectura me hace pensar que tengo un error donde el bloque final es hash dos veces ... Para ser un MD5 preciso, tendrías que detectar el EOS y manejar el último bloque de forma diferente. –
tal vez no sea la mejor opción, pero me gustaría optar por ir a Stream
descendiente/envoltura, el que sería el paso a través de una realidad escribir el archivo en el disco.
Así:
- derivar de
Stream
- tienen uno de los miembros, como
Stream _inner;
que será el flujo de destino para escribir - implemento
Write()
y todas las cosas relacionadas con - en
Write()
hash de los bloques de datos y llamada_inner.Write()
Ejemplo de uso
Stream s = File.Open("infile.dat");
Stream out = File.Create("outfile.dat");
HashWrapStream hasher = new HashWrapStream(out);
byte[] buffer=new byte[1024];
int read = 0;
while ((read=s.Read(buffer)!=0)
{
hasher.Write(buffer);
}
long hash=hasher.GetComputedHash(); // get actual hash
hasher.Dispose();
s.Dispose();
Aquí está mi solución, escribe una serie de estructuras (la variable garrapatas) como un archivo CSV (utilizando el paquete Nuget CsvHelper) y luego crea un hash para fines de suma de control mediante el sufijo. sha256
Lo hago escribiendo el csv en un memoryStream, luego escribiendo el flujo de memoria en el disco, y pasando el flujo de memoria al hash algo.
Esta solución mantiene todo el archivo como un flujo de memoria. Está bien para todo excepto para archivos de varios gigabytes que te sacarían de ram. Si tuviera que hacer esto de nuevo, probablemente intente usar el enfoque CryptoStream, pero esto es lo suficientemente bueno para mis propósitos previsibles.
He verificado a través de una herramienta de terceros que los valores hash son válidos.
Aquí está el código:
//var ticks = **some_array_you_want_to_write_as_csv**
using (var memoryStream = new System.IO.MemoryStream())
{
using (var textWriter = new System.IO.StreamWriter(memoryStream))
{
using (var csv = new CsvHelper.CsvWriter(textWriter))
{
csv.Configuration.DetectColumnCountChanges = true; //error checking
csv.Configuration.RegisterClassMap<TickDataClassMap>();
csv.WriteRecords(ticks);
textWriter.Flush();
//write to disk
using (var fileStream = new System.IO.FileStream(targetFileName, System.IO.FileMode.Create))
{
memoryStream.Position = 0;
memoryStream.CopyTo(fileStream);
}
//write sha256 hash, ensuring that the file was properly written
using (var sha256 = System.Security.Cryptography.SHA256.Create())
{
memoryStream.Position = 0;
var hash = sha256.ComputeHash(memoryStream);
using (var reader = System.IO.File.OpenRead(targetFileName))
{
System.IO.File.WriteAllText(targetFileName + ".sha256", hash.ConvertByteArrayToHexString());
}
}
}
}
}
Este método copiar y hash con corrientes encadenadas.
private static byte[] CopyAndHash(string source, string target, Action<double> progress, Func<bool> isCanceled)
{
using(var sha512 = SHA512.Create())
using (var targetStream = File.OpenWrite(target))
using (var cryptoStream = new CryptoStream(targetStream, sha512, CryptoStreamMode.Write))
using (var sourceStream = File.OpenRead(source))
{
byte[] buffer = new byte[81920];
int read;
while ((read = sourceStream.Read(buffer, 0, buffer.Length)) > 0 && !isCanceled())
{
cryptoStream.Write(buffer, 0, read);
progress?.Invoke((double) sourceStream.Length/sourceStream.Position * 100);
}
File.SetAttributes(target, File.GetAttributes(source));
return sha512.Hash;
}
}
muestra completa ver https://gist.github.com/dhcgn/da1637277d9456db9523a96a0a34da78
- 1. Cómo guardar un hash en un CSV
- 2. Storable.pm - corrupto al guardar en un archivo no truncado
- 3. carpeta asociada al guardar un archivo html
- 4. ¿Guardar un hash MD5 de un archivo de texto en el mismo archivo de texto?
- 5. Guardar un archivo temporal
- 6. guardar Excepciones al archivo en python
- 7. Guardar WriteableBitmap al archivo usando WPF
- 8. Problemas al guardar una foto en un archivo
- 9. Cómo guardar memoria al leer un archivo en Php?
- 10. .net grid computing computing migration, recomendaciones sobre bibliotecas, arquitectura
- 11. Establecer extensión de archivo inicial al guardar el archivo
- 12. Raytracer - Computing Eye Rays
- 13. Python Distributed Computing (works)
- 14. Python High Performance Computing
- 15. Guardar un HASH a Redis en una aplicación de rieles
- 16. Analizando un archivo torrent - información hash. (Erlang)
- 17. ¿Guardar un NSView en un archivo png?
- 18. Guardar un TObject en un archivo
- 19. Eclipse: al guardar ejecutar un programa
- 20. Problema de pollo/huevo: hash de archivo (incluido hash) dentro de un archivo! ¿Posible?
- 21. Guardar salida de un archivo php en un archivo html
- 22. Cómo agregar un nuevo elemento al hash
- 23. PHP agregar nodo al archivo xml existente y guardar
- 24. QFileDialog: ¿agregar extensión automáticamente al guardar el archivo?
- 25. problema al guardar el archivo pdf en R con ggplot2
- 26. C# - Guardar lista <T> al archivo XML
- 27. ¿Cómo after_save trabajo al guardar un objeto
- 28. Redis devuelve un error al intentar guardar
- 29. Java: Guardar StreamResult en un archivo
- 30. ¿Guardar CGImageRef en un archivo png?
me hizo una pregunta similar hace poco: http://stackoverflow.com/questions/10985282/generate-running-hash-or-checksum-in-c (las respuestas son probablemente aplicable aquí debido a las restricciones), asumí que "hash" significaba MD5, SHAx, etc. –
He usado SHA256Cng y también puedo guardar el archivo.Mi pregunta es más sobre hacer ambas cosas al mismo tiempo (usando tareas/futuros) o secuencialmente (leer una secuencia de archivos mueve el puntero interno, por lo que puedo restablecer el puntero a cero o duplicar el puntero). No sé cuál es mejor y cómo hacerlo. – Dave
* reflexiona sobre leer la pregunta vinculada * (También considere un "divisor de flujo", que podría usarse para reducir potencialmente algunos trabajos manuales de copia entre dos flujos de salida). –