Генерация сигнатуры файла. Потеря памяти - C#
Формулировка задачи:
Нужно написать программу, которая будет генерировать сигнатуру. Файл делим на заданные блоки и их хэшируем ( hash-функции SHA256), и вместе с номером блока выводим в консоль. Нужно чтобы программа могла обработать файлы, размер которых больше озу. При работе с потоками допускается использовать только стандартные классы и библиотеки из .Net 3.5 (исключая ThreadPool, BackgroundWorker, TPL).
Проблема заключается в том что периодически вылетает программа при этом пишет что очередь пуста. Понимаю что косяк скорее с событиями, но не могли бы вы подсказать как можно было бы реализовать это.
И ещё проблема с огромными затратами памяти, как реализовать чтобы по экономичнее вышло и не вылетало если размер файла больше озу
namespace Signature { class GenericSignature { int _numProcs; long _blockSize; long _blockCount; long _fileSize; string _path; Queue<byte[]> _queueBlockFile; private EventWaitHandle _eventBlockRead; public GenericSignature(string path, int size) { _blockSize = size; _path = path; _blockCount = 0; _queueBlockFile = new Queue<byte[]>(); _eventBlockRead = new EventWaitHandle(false, EventResetMode.AutoReset); } public void signatureCreate() { try { _numProcs = Environment.ProcessorCount; ThreadStart read = new ThreadStart(readFile); ThreadStart hash = new ThreadStart(hashCreate); Thread readThread = new Thread(read); Thread hashThread = new Thread(hash); readThread.Start(); hashThread.Start(); readThread.Join(); hashThread.Join(); } catch (Exception e) { Console.WriteLine(e); Console.WriteLine(e.StackTrace); } } private void readFile() { byte[] portion; try { using (FileStream sourceStream = new FileStream(_path, FileMode.Open)) { _fileSize = sourceStream.Length; _blockCount = sourceStream.Length / _blockSize; for (int i = 0; i <= _blockCount; i++) { if (i == _blockCount) portion = new byte[_fileSize - _blockSize * i]; else portion = new byte[_blockSize]; sourceStream.Read(portion, 0, portion.Length); Monitor.Enter(_queueBlockFile); _queueBlockFile.Enqueue(portion); Monitor.Exit(_queueBlockFile); _eventBlockRead.Set(); } } } catch (Exception e) { Console.WriteLine(e); Console.WriteLine(e.StackTrace); } } private void hashCreate() { //try //{ byte[] portion; SHA256 sha = SHA256Managed.Create(); byte[] hash; _eventBlockRead.WaitOne(); for (int i = 0; i <= _blockCount; i++) { Monitor.Enter(_queueBlockFile); while (_queueBlockFile.Count == 0) { Thread.Sleep(10); } portion = _queueBlockFile.Dequeue(); Monitor.Exit(_queueBlockFile); if (portion == null) { _eventBlockRead.WaitOne(); } else { hash = sha.ComputeHash(portion); Console.WriteLine("блок {0}", i, BitConverter.ToString(hash)); } } /*} catch (Exception e) { Console.WriteLine(e); Console.WriteLine(e.StackTrace); }*/ } } class Program { static void Main(string[] args) { string inPath = @"E://batalon.mkv";//сделать ввод из консоли!!! int sizeBlock = 100000; GenericSignature sig = new GenericSignature(inPath, sizeBlock); sig.signatureCreate(); } } }
Решение задачи: «Генерация сигнатуры файла. Потеря памяти»
textual
Листинг программы
private void readFile() { byte[] portion; try { using (FileStream sourceStream = new FileStream(_path, FileMode.Open)) { _fileSize = sourceStream.Length; _blockCount = sourceStream.Length / _blockSize; for (int i = 0; i <= _blockCount; i++) { if (i == _blockCount) portion = new byte[_fileSize - _blockSize * i]; else portion = new byte[_blockSize]; sourceStream.Read(portion, 0, portion.Length); bool full; do { Monitor.Enter(_queueBlockFile); full = _queueBlockFile.Count >= 16; Monitor.Exit(_queueBlockFile); if (full) Thread.Sleep(10); } while (full); Monitor.Enter(_queueBlockFile); _queueBlockFile.Enqueue(portion); Monitor.Exit(_queueBlockFile); } } } catch (Exception e) { Console.WriteLine(e); Console.WriteLine(e.StackTrace); } } private void hashCreate() { SHA256 sha = SHA256Managed.Create(); for (int i = 0; i <= _blockCount; i++) { bool empty; do { Monitor.Enter(_queueBlockFile); empty = _queueBlockFile.Count == 0; Monitor.Exit(_queueBlockFile); if (empty) Thread.Sleep(10); } while (empty); Monitor.Enter(_queueBlockFile); byte[] portion = _queueBlockFile.Dequeue(); Monitor.Exit(_queueBlockFile); byte[] hash = sha.ComputeHash(portion); Console.WriteLine("блок {0}: {1}", i, BitConverter.ToString(hash)); } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д