/// <summary> /// Получить части архивированного потока. /// </summary> /// <param name="sourceStream">Архивированный поток.</param> /// <returns>Список частей архива.</returns> private List <ArchivePart> GetArchiveParts(Stream sourceStream) { if (_archiveParts != null && _archiveParts.Any()) { return(_archiveParts); } long offset = 0; var portionSizeBufferLength = sizeof(long); var portionSizeBuffer = new byte[portionSizeBufferLength]; var parts = new List <ArchivePart>(); while (offset + portionSizeBufferLength < sourceStream.Length) { sourceStream.Seek(offset, SeekOrigin.Begin); sourceStream.Read(portionSizeBuffer, 0, portionSizeBufferLength); var portionBufferLength = BitConverter.ToInt32(portionSizeBuffer, 0); offset += portionSizeBufferLength; var archivePart = new ArchivePart(offset, portionBufferLength); parts.Add(archivePart); offset += portionBufferLength; } return(parts); }
/// <summary> /// Выполнить архивацию файла. /// </summary> /// <param name="sourceStream">Исходный поток.</param> /// <param name="targetStream">Архивированный поток.</param> /// <param name="bufferSize">Размер буфера.</param> private void CompressInternal(Stream sourceStream, Stream targetStream, long bufferSize) { var parts = Math.Ceiling((double)sourceStream.Length / bufferSize); if (bufferSize > sourceStream.Length) { bufferSize = sourceStream.Length; } for (var portion = 0; portion < parts; portion++) { var currentPortion = portion; var archivePart = new ArchivePart(); var size = bufferSize; var offset = currentPortion * size; if (offset + size > sourceStream.Length) { size = sourceStream.Length - offset; } archivePart.Offset = offset; var compressingTask = new ProcessingTask(() => { var portionArray = new byte[size]; lock (sourceStream) { sourceStream.Seek(archivePart.Offset, SeekOrigin.Begin); sourceStream.Read(portionArray, 0, (int)size); } archivePart.Input = portionArray; archivePart.Compress(); }); _queueManager.CompressQueue.Enqueue(compressingTask); var writingTask = new ProcessingTask(() => { while (true) { if (!archivePart.HasResult) { continue; } lock (targetStream) archivePart.WriteResult(targetStream); break; } }); _queueManager.WritingQueue.Enqueue(writingTask); } }