Exemplo n.º 1
0
        private void Compress(Stream source, Stream dest)
        {
            //Вычислим кол-во блоков
            var blocksCount = (int)(source.Length / BlockSize + (source.Length % BlockSize > 0 ? 1 : 0));

            //Создадим заголовок
            var header = new DummyCompressedDataHeader(blocksCount);

            //И оставим в потоке назначения место под запись заголовка
            dest.Seek(header.SelfSize, SeekOrigin.Begin);

            source.Seek(0, SeekOrigin.Begin);

            var blockIndex     = 0;
            var destBlockIndex = 0;
            var doneEvent      = new AutoResetEvent(false);

            while (source.Position < source.Length) //Пока не прочли весь исходный файл
            {
                if (_cancellationToken.WaitOne(0))
                {
                    return;                           //Если было событие отмены - вывалимся
                }
                var data       = new byte[BlockSize]; //Читаем блок
                var dataLength = source.Read(data, 0, BlockSize);
                var index      = blockIndex;
                //Отправляем в очередь на упаковку
                AddToDeCompressionQueue(CompressionMode.Compress, data, dataLength, result => {
                    lock (_destLocker)
                    {
                        //После упаковки блока отметим в заголовке его расположение и реальный и исходный размеры
                        header.Blocks[destBlockIndex].Number     = index;
                        header.Blocks[destBlockIndex].Size       = result.Length;
                        header.Blocks[destBlockIndex].SourceSize = dataLength;
                        //Ну и запишем его
                        dest.Write(result, 0, result.Length);
                        //Если записали все, сигнализируем об этом
                        if (++destBlockIndex == blocksCount)
                        {
                            doneEvent.Set();
                        }
                    }
                });
                blockIndex++;
                ReportProgress(blockIndex, blocksCount);
            }

            doneEvent.WaitOne(); //Подождем пока все потоки доработают
            lock (_destLocker)
            {
                //Когда все закончено, встанем в начала файла назначения
                dest.Seek(0, SeekOrigin.Begin);
                //И запишем заголовок
                header.WriteTo(dest);
            }
        }
Exemplo n.º 2
0
        private void Decompress(Stream source, Stream dest)
        {
            var header = DummyCompressedDataHeader.ReadFrom(source); //Прочтем хидер

            dest.Seek(0, SeekOrigin.Begin);

            var blockIndex       = 0;
            var writedBlockCount = 0;
            var doneEvent        = new AutoResetEvent(false);

            while (source.Position < source.Length) //Начнем читать исходный файл
            {
                if (_cancellationToken.WaitOne(0))
                {
                    return;                                //Если запросили прерывание - отвалимся
                }
                var sourceBlockSize  = header.Blocks[blockIndex].Size;
                var sourceBlockIndex = header.Blocks[blockIndex].Number;
                var data             = new byte[sourceBlockSize];
                var dataLength       = source.Read(data, 0, sourceBlockSize);
                if (dataLength != sourceBlockSize)
                {
                    throw new FileLoadException("Исходный файл имеет неверный формат");
                }

                AddToDeCompressionQueue(CompressionMode.Decompress, data, sourceBlockSize, result =>
                {
                    //Рассчитаем оригинальное смещение блока
                    var blockOffset = header.CalcSourceBlockOffset(sourceBlockIndex);

                    lock (_destLocker)
                    {
                        //И запишем его по оригинальному смещению
                        dest.Seek(blockOffset, SeekOrigin.Begin);
                        dest.Write(result, 0, result.Length);

                        if (++writedBlockCount == header.BlocksCount)
                        {
                            doneEvent.Set();
                        }
                    }
                });
                blockIndex++;
                ReportProgress(blockIndex, header.BlocksCount);
            }

            doneEvent.WaitOne();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Читает заголовок из указанного потока
        /// </summary>
        /// <param name="source">Поток-источник</param>
        /// <returns></returns>
        internal static DummyCompressedDataHeader ReadFrom(Stream source)
        {
            var breader = new BinaryReader(source);
            var header  = breader.ReadUInt32();

            if (header != Header)
            {
                throw new FileLoadException("Указанный файл имеет неверный формат (Заголовок не соответствует ожидаемому)");
            }

            var count  = breader.ReadInt32();
            var result = new DummyCompressedDataHeader(count);

            for (var idx = 0; idx < count; idx++)
            {
                result.Blocks[idx].ReadFrom(breader);
            }
            return(result);
        }