/// <summary> /// Background compression of input file to output file. Input file will be copied first in main thread to temp file. /// </summary> /// <param name="inputFile"></param> /// <param name="outputFile"></param> private static void BZip(string inputFile, string outputFile, int level = 1) { var temp = string.Empty; var tempOutputFile = outputFile; if (File.Exists("D:\\DATALOSS_WARNING_README.txt")) // Running on Azure { // copy temp file to local storage temp = Path.Combine("D:\\", Path.GetFileName(outputFile)) + ".tmp"; tempOutputFile = Path.Combine("D:\\", Path.GetFileName(outputFile)); } else { temp = outputFile + ".tmp"; } File.Copy(inputFile, temp, true); File.WriteAllBytes(outputFile, new byte[0]); // touches the output file to prevent further backup // runs backup in background Task.Run(() => { try { // not using parallel because it will slow down the entire server using (var fs = File.Open(temp, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var bz = new Ionic.BZip2.ParallelBZip2OutputStream(File.OpenWrite(tempOutputFile), level)) { fs.CopyTo(bz); } if (tempOutputFile != outputFile) { File.Copy(tempOutputFile, outputFile, true); File.Delete(tempOutputFile); } } catch (Exception) { File.Delete(outputFile); } finally { File.Delete(temp); } }); }
/// <summary> /// Function to compress data. /// </summary> /// <param name="inStream">Input stream.</param> /// <param name="outStream">Output stream.</param> /// <param name="writeBuffer">The buffer used to transfer data from one stream to another.</param> /// <param name="compressionRate">The value used to define how well to compress the data.</param> /// <param name="token">The token used to cancel the operation.</param> private void CompressData(Stream inStream, Stream outStream, byte[] writeBuffer, int compressionRate, CancellationToken token) { Debug.Assert(outStream != null, "outStream != null"); using (var bzStream = new Ionic.BZip2.ParallelBZip2OutputStream(outStream, compressionRate, true)) { long streamSize = inStream.Length; while (streamSize > 0) { if (token.IsCancellationRequested) { return; } int readSize = inStream.Read(writeBuffer, 0, writeBuffer.Length); if (token.IsCancellationRequested) { return; } if (readSize > 0) { if (token.IsCancellationRequested) { return; } bzStream.Write(writeBuffer, 0, readSize); if (token.IsCancellationRequested) { return; } } streamSize -= readSize; } } }
private Stream MaybeApplyCompression(Stream s, long streamLength) { if (_CompressionMethod == 0x08 && CompressionLevel != Ionic.Zlib.CompressionLevel.None) { #if !NETCF // ParallelDeflateThreshold == 0 means ALWAYS use parallel deflate // ParallelDeflateThreshold == -1L means NEVER use parallel deflate // Other values specify the actual threshold. if (_container.ParallelDeflateThreshold == 0L || (streamLength > _container.ParallelDeflateThreshold && _container.ParallelDeflateThreshold > 0L)) { // This is sort of hacky. // // It's expensive to create a ParallelDeflateOutputStream, because // of the large memory buffers. But the class is unlike most Stream // classes in that it can be re-used, so the caller can compress // multiple files with it, one file at a time. The key is to call // Reset() on it, in between uses. // // The ParallelDeflateOutputStream is attached to the container // itself - there is just one for the entire ZipFile or // ZipOutputStream. So it gets created once, per save, and then // re-used many times. // // This approach will break when we go to a "parallel save" // approach, where multiple entries within the zip file are being // compressed and saved at the same time. But for now it's ok. // // instantiate the ParallelDeflateOutputStream if (_container.ParallelDeflater == null) { _container.ParallelDeflater = new Ionic.Zlib.ParallelDeflateOutputStream(s, CompressionLevel, _container.Strategy, true); // can set the codec buffer size only before the first call to Write(). if (_container.CodecBufferSize > 0) _container.ParallelDeflater.BufferSize = _container.CodecBufferSize; if (_container.ParallelDeflateMaxBufferPairs > 0) _container.ParallelDeflater.MaxBufferPairs = _container.ParallelDeflateMaxBufferPairs; } // reset it with the new stream Ionic.Zlib.ParallelDeflateOutputStream o1 = _container.ParallelDeflater; o1.Reset(s); return o1; } #endif var o = new Ionic.Zlib.DeflateStream(s, Ionic.Zlib.CompressionMode.Compress, CompressionLevel, true); if (_container.CodecBufferSize > 0) o.BufferSize = _container.CodecBufferSize; o.Strategy = _container.Strategy; return o; } #if BZIP if (_CompressionMethod == 0x0c) { #if !NETCF if (_container.ParallelDeflateThreshold == 0L || (streamLength > _container.ParallelDeflateThreshold && _container.ParallelDeflateThreshold > 0L)) { var o1 = new Ionic.BZip2.ParallelBZip2OutputStream(s, true); return o1; } #endif var o = new Ionic.BZip2.BZip2OutputStream(s, true); return o; } #endif return s; }
private Stream MaybeApplyCompression(Stream s, long streamLength) { if (_CompressionMethod == 0x08 && CompressionLevel != Ionic.Zlib.CompressionLevel.None) { var o = new Ionic.Zlib.DeflateStream(s, Ionic.Zlib.CompressionMode.Compress, CompressionLevel, true); if (_container.CodecBufferSize > 0) o.BufferSize = _container.CodecBufferSize; o.Strategy = _container.Strategy; return o; } #if BZIP if (_CompressionMethod == 0x0c) { #if !NETCF if (_container.ParallelDeflateThreshold == 0L || (streamLength > _container.ParallelDeflateThreshold && _container.ParallelDeflateThreshold > 0L)) { var o1 = new Ionic.BZip2.ParallelBZip2OutputStream(s, true); return o1; } #endif var o = new Ionic.BZip2.BZip2OutputStream(s, true); return o; } #endif return s; }