/// <summary> /// </summary> /// <param name="p_StreamDataForReading"></param> /// <param name="p_CompressModuleIdentifier"></param> /// <param name="p_CompressOnlyStreamWithMinimumLength"></param> /// <param name="p_CompressOnlyRatioToPercent"> /// Calculate Compress/Decompress*100. Compress only if calculated value is /// smaller than this setting /// </param> /// <param name="p_ChunkSizeOfStreamDataForCompress"></param> public StreamReadCompress(Stream p_StreamDataForReading, string p_CompressModuleIdentifier, int p_CompressOnlyStreamWithMinimumLength = 0, byte p_CompressOnlyRatioToPercent = 100, int p_ChunkSizeOfStreamDataForCompress = ReadedChunkSizeBeforeCompressDefaultValue) { _CompressOnlyStreamWithMinimumLength = p_CompressOnlyStreamWithMinimumLength; _CompressOnlyRatioToPercent = p_CompressOnlyRatioToPercent; _ReadedChunkSizeBeforeCompress = p_ChunkSizeOfStreamDataForCompress > ReadedChunkSizeBeforeCompressDefaultValue ? ReadedChunkSizeBeforeCompressDefaultValue : p_ChunkSizeOfStreamDataForCompress; _StreamDataForReading = p_StreamDataForReading ?? throw new ArgumentNullException(nameof(p_StreamDataForReading)); _StreamCompressedData = new MemoryStream(); _BufferOriginalData = new byte[_ReadedChunkSizeBeforeCompress]; byte[] compressModuleIdentifier = Encoding.UTF8.GetBytes(p_CompressModuleIdentifier); if (compressModuleIdentifier.Length > 0) { //Defined, must compress if (compressModuleIdentifier.Length != 4) { throw new ArgumentOutOfRangeException(nameof(p_CompressModuleIdentifier), p_CompressModuleIdentifier, "p_CompressModuleIdentifier must be 4 chars length"); } _CompressModule = new StreamReadModules().FindByHeaderIdentification(compressModuleIdentifier); if (_CompressModule == null) { throw new Exception($"StreamReadModule with HeaderIdentification = {Encoding.UTF8.GetString(compressModuleIdentifier)} not found"); } } }
public void ReadDataAndStartCompressingInTask(Stream p_StreamDataForReading, StreamReadModule p_CompressModule, int p_ReadedChunkSizeBeforeCompress, int p_CompressOnlyStreamWithMinimumLength, int p_CompressOnlyRatioToPercent) { #if log Log("ManualResetEvent.WaitOne Reset"); #endif _ManualResetEvent.Reset(); var readedUncompressedChunkSize = p_StreamDataForReading.Read(_BufferOriginalData, 0, p_ReadedChunkSizeBeforeCompress); #if log Log( $"Readed {readedUncompressedChunkSize} from StreamDataForReading (Position = {p_StreamDataForReading.Position})"); #endif Task.Factory.StartNew(() => CompressData(readedUncompressedChunkSize, p_CompressModule, p_CompressOnlyStreamWithMinimumLength, p_CompressOnlyRatioToPercent)); }
/// <summary> /// </summary> /// <param name="p_StreamDataForReading"></param> /// <param name="p_CompressModuleIdentifier"></param> /// <param name="p_CompressOnlyStreamWithMinimumLength"></param> /// <param name="p_CompressOnlyRatioToPercent"> /// Calculate Compress/Decompress*100. Compress only if calculated value is /// smaller than this setting /// </param> /// <param name="p_ChunkSizeOfStreamDataForCompress"></param> /// <param name="p_PreparedChunks"></param> public StreamReadPrecompressedChunks(Stream p_StreamDataForReading, string p_CompressModuleIdentifier, int p_CompressOnlyStreamWithMinimumLength = 0, byte p_CompressOnlyRatioToPercent = 100, int p_ChunkSizeOfStreamDataForCompress = ReadedChunkSizeBeforeCompressDefaultValue, int p_PreparedChunks = 1) { _CompressOnlyStreamWithMinimumLength = p_CompressOnlyStreamWithMinimumLength; _CompressOnlyRatioToPercent = p_CompressOnlyRatioToPercent; _PreparedChunks = p_PreparedChunks; _ReadedChunkSizeBeforeCompress = p_ChunkSizeOfStreamDataForCompress > ReadedChunkSizeBeforeCompressDefaultValue ? ReadedChunkSizeBeforeCompressDefaultValue : p_ChunkSizeOfStreamDataForCompress; _StreamDataForReading = p_StreamDataForReading ?? throw new ArgumentNullException(nameof(p_StreamDataForReading)); _Chunks = new List <ChunkCompress>(p_PreparedChunks); for (var i = 0; i < p_PreparedChunks; i++) #if log { _Chunks.Add(new Chunk(i, new byte[_ReadedChunkSizeBeforeCompress], new MemoryStream(), Log)); } #else { _Chunks.Add(new ChunkCompress(i, new byte[_ReadedChunkSizeBeforeCompress], new MemoryStream(), null)); } #endif var compressModuleIdentifier = Encoding.UTF8.GetBytes(p_CompressModuleIdentifier); if (compressModuleIdentifier.Length > 0) { //Defined, must compress if (compressModuleIdentifier.Length != 4) { throw new ArgumentOutOfRangeException(nameof(p_CompressModuleIdentifier), p_CompressModuleIdentifier, "p_CompressModuleIdentifier must be 4 chars length"); } _CompressModule = new StreamReadModules().FindByHeaderIdentification(compressModuleIdentifier); if (_CompressModule == null) { throw new Exception( $"StreamReadModule with HeaderIdentification = {Encoding.UTF8.GetString(compressModuleIdentifier)} not found"); } } _Chunks.ForEach(ch => ch.ReadDataAndStartCompressingInTask(_StreamDataForReading, _CompressModule, _ReadedChunkSizeBeforeCompress, _CompressOnlyStreamWithMinimumLength, _CompressOnlyRatioToPercent)); }
private void DecompressData(int readed, StreamReadModule module, int uncompressedChunkSize) { _StreamCompressedData.Position = 0; _StreamCompressedData.Write(_BufferCompressedData, 0, readed); _StreamCompressedData.Position = 0; //decompress data to buffer using (var gzipStream = module.ActionCreateDecompressStreamForWriting(_StreamCompressedData)) { if (_BufferDecompressedData.Length < uncompressedChunkSize) { Array.Resize(ref _BufferDecompressedData, uncompressedChunkSize); } var readedUncompressed = gzipStream.Read(_BufferDecompressedData, 0, uncompressedChunkSize); if (uncompressedChunkSize != readedUncompressed) { throw new Exception($"UncompressedChunkSize must be {uncompressedChunkSize}B but stream returns {readedUncompressed}B"); } _BufferDecompressedDataPosition = 0; _BufferDecompressedDataLength = uncompressedChunkSize; } _ManualResetEvent.Set(); }
public void CompressData(int p_ReadedUncompressedChunkSize, StreamReadModule p_CompressModule, int p_CompressOnlyStreamWithMinimumLength, int p_CompressOnlyRatioToPercent) { if (p_ReadedUncompressedChunkSize == 0) { StreamReadCompressSource = StreamReadCompressSourceEnum.None; #if log Log($"Compress[{_Key}] returns StreamReadCompressSource=None"); #endif ManualResetEventSetAndLog(); return; } _BufferOriginalDataLength = p_ReadedUncompressedChunkSize; _BufferOriginalDataPosition = 0; //Check if compression needed if (p_CompressModule == null || p_ReadedUncompressedChunkSize <= p_CompressOnlyStreamWithMinimumLength) { #if log StreamReadCompressSource = StreamReadCompressSourceEnum.BufferOriginalData; Log( $"Compress[{_Key}] returns StreamReadCompressSource=BufferOriginalData (CompressOnlyStreamWithMinimumLength)"); #endif ManualResetEventSetAndLog(); return; } //Compression needed _StreamCompressedData.Position = 0; using (var streamCompressForWriting = p_CompressModule.ActionCreateCompressStreamForWriting(_StreamCompressedData)) { #if log Log("Compress begin"); #endif streamCompressForWriting.Write(_BufferOriginalData, 0, p_ReadedUncompressedChunkSize); #if log Log("Compress end"); #endif } var compressRatioPercent = _StreamCompressedData.Position / (decimal)p_ReadedUncompressedChunkSize * 100m; var compressedLargerThanOriginal = _StreamCompressedData.Position + 12 > p_ReadedUncompressedChunkSize; if (compressedLargerThanOriginal || compressRatioPercent >= p_CompressOnlyRatioToPercent) { //Compressed data is larger then configurable limits, use original data StreamReadCompressSource = StreamReadCompressSourceEnum.BufferOriginalData; #if log Log( "Compress returns StreamReadCompressSource=BufferOriginalData (compressed larger then configurable limit)"); #endif ManualResetEventSetAndLog(); return; } _StreamCompressedDataLength = (int)_StreamCompressedData.Position; _StreamCompressedData.Position = 0; StreamReadCompressSource = StreamReadCompressSourceEnum.StreamCompressedData; #if log Log( $"Compress returns CompressedData ({_StreamCompressedDataLength} B) (First buffer of this chain will be {_StreamCompressedDataLength} B + 12 B Header={_StreamCompressedDataLength + 12} B)"); #endif ManualResetEventSetAndLog(); }