/// <summary> /// Compress the entirety of the MemoryStream to the destination Stream, or if compressing increases the size, just copy the original data over /// </summary> /// <param name="uncompressedSource">A MemoryStream that will have its full contents compressed</param> /// <param name="compressedDestination">Output Stream to write results to</param> /// <param name="compressionKind">Compression Type</param> /// <param name="compressionStrategy">The balance of speed vs size for the compressor</param> public static void CompressCopyTo(MemoryStream uncompressedSource, IOStream compressedDestination, CompressionKind compressionKind, CompressionStrategy compressionStrategy) { uncompressedSource.Seek(0, SeekOrigin.Begin); if (compressionKind == CompressionKind.None) { uncompressedSource.CopyTo(compressedDestination); } else { var temporaryStream = new MemoryStream(); //How can we avoid this?? We need to know the length of the compressed stream to write the header before we can write the stream itself... using (var compressingStream = CompressionFactory.CreateCompressorStream(compressionKind, compressionStrategy, temporaryStream)) uncompressedSource.CopyTo(compressingStream); if (temporaryStream.Length >= uncompressedSource.Length) { //Write the original data rather than the compressed data uncompressedSource.Seek(0, SeekOrigin.Begin); WriteBlockHeader(compressedDestination, (int)uncompressedSource.Length, false); uncompressedSource.CopyTo(compressedDestination); } else { temporaryStream.Seek(0, SeekOrigin.Begin); WriteBlockHeader(compressedDestination, (int)temporaryStream.Length, true); temporaryStream.CopyTo(compressedDestination); } } }
/// <summary> /// Provides a Stream that when read from, reads consecutive blocks of compressed data from an ORC Stream. /// All data in the <paramref name="inputStream"/> will be consumed. /// </summary> public static IOStream GetDecompressingStream(IOStream inputStream, CompressionKind compressionKind) { if (compressionKind == CompressionKind.None) { return(inputStream); } else { return(new ConcatenatingStream(() => { int blockLength; bool isCompressed; bool headerAvailable = ReadBlockHeader(inputStream, out blockLength, out isCompressed); if (!headerAvailable) { return null; } var streamSegment = new StreamSegment(inputStream, blockLength, true); if (!isCompressed) { return streamSegment; } else { return CompressionFactory.CreateDecompressorStream(compressionKind, streamSegment); } }, false)); } }