public void InputStreamOwnership() { var memStream = new TrackedMemoryStream(); var s = new LzwInputStream(memStream); Assert.IsFalse(memStream.IsClosed, "Shouldnt be closed initially"); Assert.IsFalse(memStream.IsDisposed, "Shouldnt be disposed initially"); #if NET451 s.Close(); #elif NETCOREAPP1_0 s.Dispose(); #endif Assert.IsTrue(memStream.IsClosed, "Should be closed after parent owner close"); Assert.IsTrue(memStream.IsDisposed, "Should be disposed after parent owner close"); memStream = new TrackedMemoryStream(); s = new LzwInputStream(memStream); Assert.IsFalse(memStream.IsClosed, "Shouldnt be closed initially"); Assert.IsFalse(memStream.IsDisposed, "Shouldnt be disposed initially"); s.IsStreamOwner = false; #if NET451 s.Close(); #elif NETCOREAPP1_0 s.Dispose(); #endif Assert.IsFalse(memStream.IsClosed, "Should not be closed after parent owner close"); Assert.IsFalse(memStream.IsDisposed, "Should not be disposed after parent owner close"); }
public static void ExtractArchive(string archivePath, string destinationDirectory, CancellationTokenEx cancellationToken, ReportCompressionStatus reportCompressionStatus, AddProcessingEntry addProcessingEntry) { bool isTar; Stream inputStream = new FileStream(archivePath, FileMode.Open, FileAccess.Read); switch (Path.GetExtension(archivePath).ToUpper()) { case ".ZIP": var fastZip = new FastZip(); fastZip.ExtractZip(inputStream, destinationDirectory, FastZip.Overwrite.Always, null, null, null, true, true); //TODO: Add progress return; case ".TAR": isTar = true; break; case ".GZ": inputStream = new GZipInputStream(inputStream) { IsStreamOwner = true }; isTar = archivePath.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase); break; case ".BZ2": inputStream = new BZip2InputStream(inputStream) { IsStreamOwner = true }; isTar = archivePath.EndsWith(".tar.bz2", StringComparison.OrdinalIgnoreCase); break; case ".LZW": inputStream = new LzwInputStream(inputStream) { IsStreamOwner = true }; isTar = archivePath.EndsWith(".tar.lzw", StringComparison.OrdinalIgnoreCase); break; default: inputStream.Dispose(); return; } Directory.CreateDirectory(destinationDirectory); using (inputStream) { if (isTar) { using (TarArchive tarArchive = TarArchive.CreateInputTarArchive(inputStream)) { TarEntry lastEntry = null; ProcessingEntry lastProcessingEntry = null; tarArchive.ProgressMessageEvent += (archive, entry, message) => { if (lastEntry != entry) { if (lastEntry != null) { lastProcessingEntry.Progress = 1; lastProcessingEntry.Size = entry.Size; ThreadPool.QueueUserWorkItem(state => reportCompressionStatus(lastProcessingEntry)); } lastEntry = entry; lastProcessingEntry = new ProcessingEntry { Action = ProcessingEntryAction.Extracting, CreationTime = DateTime.UtcNow, Path = entry.File, Progress = 0, Name = entry.Name }; ThreadPool.QueueUserWorkItem(state => addProcessingEntry(lastProcessingEntry)); } }; tarArchive.ExtractContents(destinationDirectory); } } else { var filename = Path.GetFileNameWithoutExtension(archivePath); var destinationFilePath = Path.Combine(destinationDirectory, filename); var processingEntry = new ProcessingEntry { Action = ProcessingEntryAction.Extracting, CreationTime = DateTime.UtcNow, IsDirectory = false, IsInterminate = false, LastAccess = DateTime.UtcNow, Path = destinationFilePath, Name = filename }; byte[] dataBuffer = new byte[4096]; using (var destinationFileStream = new FileStream(destinationFilePath, FileMode.Create, FileAccess.ReadWrite)) { addProcessingEntry(processingEntry); StreamUtils.Copy(inputStream, destinationFileStream, dataBuffer, (sender, args) => { processingEntry.Progress = args.PercentComplete / 100; processingEntry.Size = destinationFileStream.Length; args.ContinueRunning = !cancellationToken.IsCanceled; ThreadPool.QueueUserWorkItem(state => reportCompressionStatus.Invoke(processingEntry)); }, TimeSpan.FromSeconds(1), null, null); if (cancellationToken.IsCanceled) { processingEntry.Progress = -1; ThreadPool.QueueUserWorkItem(state => reportCompressionStatus.Invoke(processingEntry)); return; } processingEntry.Progress = 1; processingEntry.Size = destinationFileStream.Length; ThreadPool.QueueUserWorkItem(state => reportCompressionStatus.Invoke(processingEntry)); } } } }