public void InputStreamOwnership() { TrackedMemoryStream memStream = new TrackedMemoryStream(); LzwInputStream s = new LzwInputStream(memStream); Assert.IsFalse(memStream.IsClosed, "Shouldnt be closed initially"); Assert.IsFalse(memStream.IsDisposed, "Shouldnt be disposed initially"); s.Close(); 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; s.Close(); Assert.IsFalse(memStream.IsClosed, "Should not be closed after parent owner close"); Assert.IsFalse(memStream.IsDisposed, "Should not be disposed after parent owner close"); }
/// <summary> /// Create Lzw file provider from byte[]. /// /// Has one entry by name of <paramref name="entryName"/>. /// Reads the whole stream once just to get the entry length. /// </summary> /// <param name="data"></param> /// <param name="entryName"></param> /// <param name="hintPath">(optional) clue of the file that is being opened</param> /// <param name="lastModified">Date time for folder entries</param> /// <exception cref="IOException"></exception> public LzwFileProvider(byte[] data, string entryName, string hintPath = null, DateTimeOffset?lastModified = default) : base(hintPath, lastModified) { if (data == null) { throw new ArgumentNullException(nameof(data)); } // Mutable long, and object to take closure reference to. long[] lengthContainer = new long[] { -1 }; Stream opener() { MemoryStream ms = new MemoryStream(data); try { LzwInputStream lzis = new LzwInputStream(ms) { IsStreamOwner = true }; return(lengthContainer[0] < 0L ? lzis : (Stream) new LzwStreamFix(lzis, null, null, lengthContainer[0])); } catch (Exception) when(_closeStream(ms)) { throw new IOException($"Failed to read .Lzw from byte[]"); } } // Calculate length by reading the whole thing. lengthContainer[0] = CalculateLength(opener); this.streamProvider = new StreamOpener(opener, entryName, belatedDisposeList); this.root.files[entryName] = new ArchiveFileEntry(this.streamProvider, entryName, entryName, lengthContainer[0], lastModified ?? DateTimeOffset.MinValue); }
/// <summary> /// Create Lzw file provider from .z file. /// /// Has one entry by name of <paramref name="entryName"/>. /// Reads the whole stream once just to get the entry length. /// </summary> /// <param name="filepath"></param> /// <param name="entryName"></param> /// <param name="hintPath">(optional) clue of the file that is being opened</param> /// <param name="lastModified">Date time for folder entries</param> /// <exception cref="IOException"></exception> public LzwFileProvider(string filepath, string entryName, string hintPath = null, DateTimeOffset?lastModified = default) : base(hintPath, lastModified) { // Mutable long, and object to take closure reference to. long[] lengthContainer = new long[] { -1 }; Func <Stream> opener = () => { FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read); try { LzwInputStream lzis = new LzwInputStream(fs); lzis.IsStreamOwner = true; return(lengthContainer[0] < 0L ? lzis : (Stream) new LzwStreamFix(lzis, null, null, lengthContainer[0])); } catch (Exception) when(_closeStream(fs)) { throw new IOException($"Failed to read .Lzw from {filepath}"); } }; // Calculate length by reading the whole thing. lengthContainer[0] = CalculateLength(opener); this.streamProvider = new StreamOpener(opener, entryName, belatedDisposeList); this.root.files[entryName] = new ArchiveFileEntry(this.streamProvider, entryName, entryName, lengthContainer[0], lastModified ?? DateTimeOffset.MinValue); }
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 void ZeroLengthInputStream() { LzwInputStream lis = new LzwInputStream(new MemoryStream()); bool exception = false; try { lis.ReadByte(); } catch { exception = true; } Assert.IsTrue(exception, "reading from an empty stream should cause an exception"); }
public static byte[] Decompress(byte[] data) { MemoryStream ot = new MemoryStream(); LzwInputStream CompInStream = new LzwInputStream(new MemoryStream(data)); int ch = CompInStream.ReadByte(); while (ch != -1) { ot.WriteByte((byte)ch); ch = CompInStream.ReadByte(); } return(ot.GetBuffer()); }
/// <summary> /// Create Length override. /// </summary> /// <param name="sourceStream"></param> /// <param name="disposeHandle"></param> /// <param name="disposeAction"></param> /// <param name="newLength"></param> public LzwStreamFix(LzwInputStream sourceStream, IDisposable disposeHandle, Action disposeAction, long newLength) : base(sourceStream, disposeHandle, disposeAction) { this.newLength = newLength; }
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)); } } } }