Mam inputStream
, którego chcę użyć do obliczenia hasza i zapisać plik na dysku. Chciałbym wiedzieć, jak to zrobić skutecznie. Czy powinienem użyć jakiegoś zadania, aby wykonać to jednocześnie, czy powinienem duplikować strumień przejścia do dwóch strumieni, jeden dla metody saveFile
i jeden dla metody computeHash
, czy powinienem zrobić coś innego?Computing Hash podczas zapisywania pliku?
Odpowiedz
Musisz rzeczy bajtów strumienia jest w byte[]
w celu ich mieszania.
Możesz także przekazać strumień. Jakie byłyby korzyści konwersji strumienia na bajt []? – Dave
Ja, z jakiegoś powodu, nie zauważyłem przeciążenia. Zawsze. Pojadę 10 razy "Hail Bills Gates" "w pokucie. – bluevector
@Dave Nie ma żadnej korzyści. Obie formy, które pobierają "byte []" i "Stream", blokują i oczekują wszystkich danych w jednym ujęciu. Z wątkami i specjalnym 'Streamem ... ... ale to tylko dodaje więcej problemów, to rozwiązuje ... –
A co z wykorzystaniem algorytmów mieszających działających na poziomie bloku? Możesz dodać blok do hasha (używając TransformBlock), a następnie zapisać blok do bloku foreach pliku w strumieniu.
Nietestowane szorstki strzał:
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;
}
Nie jestem wielkim fanem ręcznego przetwarzania bloków, ale to powinno działać. (Myślę, że CryptoStream jest prostszym podejściem, które sprowadza się do bycia ładnym opakowaniem.) –
Zgoda. Generalnie unikam ich jak zarazy (dzięki Bogu za najnowszą metodę Stream.CopyTo) ... Myślę, że jest to najlepszy sposób na rozwiązanie problemu. Również drugi odczyt sprawia, że myślę, że mam błąd, w którym ostatni blok został zakodowany dwukrotnie ... Aby być dokładnym MD5, musiałbyś wykryć EOS i obsługiwać ostatni blok w inny sposób. –
To może nie być najlepszym rozwiązaniem, ale wybrałbym iść do Stream
potomka/owijki, ten, który byłby pass-through dla jednej rzeczywiście pisanie plik dysk.
Więc:
- pochodzą z
Stream
- mieć jeden członek takich jak
Stream _inner;
który będzie strumień cel napisania - wdrożyć
Write()
i wszystkie rzeczy związane - w
Write()
hash bloków dane i zadzwoń pod numer_inner.Write()
Przykład zastosowania
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();
jest mój rozwiązanie zapisuje szereg elemencie (zmienna kleszcze) jako csv (przy użyciu zestawu Nuget CsvHelper), a następnie tworzy mieszania dla celów sumy kontrolnej z wykorzystaniem sufiksu. sha256
Robię to, pisząc csv do memoryStream, a następnie zapisując strumień pamięci na dysk, a następnie przesyłając memorystream do skrótu algo.
Dzięki temu rozwiązaniu cały plik jest przechowywany w pamięci memorystycznej. Wszystko oprócz plików wielogigabajtowych, które wyłączyłyby Cię z pamięci RAM, jest w porządku. Gdybym musiał to zrobić ponownie, prawdopodobnie spróbowałbym użyć podejścia CryptoStream, ale jest to wystarczająco dobre dla moich przewidywalnych celów.
Sprawdziłem za pomocą narzędzia innej firmy, że skróty są ważne.
Oto kod:
//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());
}
}
}
}
}
Ta metoda kopiowania i hash W powiązanych strumieni.
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;
}
}
Pełna próbka zobaczyć https://gist.github.com/dhcgn/da1637277d9456db9523a96a0a34da78
- 1. UnauthorizedAccessException podczas zapisywania pliku
- 2. QFileDialog: automatyczne dodawanie rozszerzenia podczas zapisywania pliku?
- 3. UIDocument i NSFileWrapper - NSFastEnumerationMutationHandler podczas zmiany pakowania pliku podczas zapisywania
- 4. Hash w pliku YAML?
- 5. Computing od języka R
- 6. Błąd odmowy uprawnień podczas zapisywania do pliku w języku Python
- 7. Wykonaj test jednostki podczas zapisywania pliku w PhpStorm
- 8. Rails EOFError (koniec pliku osiągnięto) podczas zapisywania użytkownika devisera
- 9. RubyMine, aby zignorować niektóre pliki podczas zapisywania pliku
- 10. Niepoprawna wartość podczas zapisywania enum
- 11. Sesja utracona podczas zapisywania cookie
- 12. Computing Podpis/Hash w JavaScript i mieć taki sam wynik jak C#
- 13. cloud computing w .net 4.0
- 14. Błąd std :: ofstream podczas zapisywania danych
- 15. VBScript do zapisywania makra w pliku Excela
- 16. Program Visual Studio 2015 RC nie tworzy pliku sourcemap podczas zapisywania pliku maszynopisu
- 17. Podczas zapisywania zeskanowanego przedmiotu i pliku, Scrapy wstawia puste wiersze w wyjściowym pliku csv
- 18. usuwanie doctype podczas zapisywania obiektu domdocument
- 19. StaleStateException podczas zapisywania encji o złożonych relacjach
- 20. Szyny: Zaktualizuj obiekt nadrzędny podczas zapisywania dziecka
- 21. Pomijanie: powiązania styków podczas zapisywania obiektu ActiveRecord
- 22. Missing rozszerzenie podczas zapisywania obrazu z płótna
- 23. Smalltalk - kolekcja jest pustym błędem podczas zapisywania
- 24. PHP do zapisywania znaków tabulacji wewnątrz pliku?
- 25. Najlepszy sposób zapisywania tablic do pliku?
- 26. Błąd podczas zapisywania nagłówków podczas zwracania FileInfo HttpResult
- 27. Jak pobrać tylko nazwę pliku z okna dialogowego zapisywania pliku
- 28. Jak wygenerować Hash dowolnego pliku w java?
- 29. Oblicz Hash zawartości pliku w C#?
- 30. Wyodrębnij hash SHA1 z pliku torrentowego
zadałem podobne pytanie niedawno: http://stackoverflow.com/questions/10985282/generate-running-hash-or-checksum-in-c (odpowiedzi są prawdopodobnie ma to zastosowanie ze względu na ograniczenia), założyłem "hash" na oznaczenie MD5, SHAx itd. –
Użyłem SHA256Cng i mogę również zapisać plik.Moje pytanie dotyczy raczej robienia obu w tym samym czasie (przy użyciu zadań/kontraktów futures) lub sekwencyjnie (odczyt strumienia filaru przesuwa wskaźnik wewnętrzny, więc mogę zresetować wskaźnik do zera lub zduplikować wskaźnik). Nie wiem, który z nich jest lepszy i jak to zrobić. – Dave
* Rozmyśla o przeczytaniu połączonego pytania * (Rozważ także "rozdzielacz strumienia", który mógłby zostać użyty do potencjalnego zmniejszenia ręcznej pracy kopiowania pomiędzy dwoma strumieniami wyjściowymi.) –