Генерация сигнатуры файла. Потеря памяти - 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));
            }
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

15   голосов , оценка 4.067 из 5
Похожие ответы