private static void WriteFileToStream(FileEntry entry, Stream target, ref ProgresHandler progresHandler) { byte[] buffer = new byte[4096]; long totalBytesRead = 0; var dataStream = entry.GetStream(); dataStream.Seek(0, SeekOrigin.Begin); while (totalBytesRead < dataStream.Length) { progresHandler.CancellationToken.ThrowIfCancellationRequested(); int bytesRemaining = (int)(dataStream.Length - totalBytesRead); int bytesToRead = buffer.Length < bytesRemaining ? buffer.Length : bytesRemaining; int bytesRead = dataStream.Read(buffer, 0, bytesToRead); totalBytesRead += bytesRead; progresHandler.BytesExtracted += bytesRead; target.Write(buffer, 0, bytesToRead); if (bytesRead == 0) { if (bytesToRead > 0) { throw new EndOfStreamException(); } break; } else { progresHandler.ReportProgress(); } } }
private static void ExtractFileEntry(FileEntry fileEntry, string destination, ref ProgresHandler progresHandler) { string destinationPath = Path.Combine(destination, fileEntry.Name); progresHandler.CurrentEntryName = fileEntry.Name; progresHandler.CurrentTargetPath = fileEntry.FullName; progresHandler.ReportProgress(); using (var fs = File.Open(destinationPath, FileMode.Create)) WriteFileToStream(fileEntry, fs, ref progresHandler); File.SetCreationTime(destinationPath, fileEntry.CreatedDate); File.SetLastWriteTime(destinationPath, fileEntry.ModifiedDate); progresHandler.ExtractedFiles++; progresHandler.ReportProgress(); }
public static void ExtractEntries( IEnumerable <LifEntry> entries, string destination, CancellationToken cancellationToken, ExtractionProgressReportDelegate progressReport) { if (!entries.Any()) { return; } var ownerLif = entries.First().Lif; var topLevel = entries.Max(x => x.GetLevel()); var entryList = entries.Where(x => x.GetLevel() == topLevel).Distinct().ToList(); if (!Directory.Exists(destination)) { Directory.CreateDirectory(destination); } var allFileEntries = entryList.OfType <FolderEntry>().SelectMany(x => x.GetAllFiles()) .Concat(entryList.OfType <FileEntry>()); var progressHandler = new ProgresHandler(ownerLif, progressReport, cancellationToken); progressHandler.TotalFiles = allFileEntries.Count(); progressHandler.TotalBytes = allFileEntries.Sum(x => x.FileSize); progressHandler.ReportProgress(); foreach (var fileEntry in entryList.OfType <FileEntry>()) { if (progressHandler.IsCancellationRequested) { break; } ExtractFileEntry(fileEntry, destination, ref progressHandler); } foreach (var folderEntry in entryList.OfType <FolderEntry>()) { if (progressHandler.IsCancellationRequested) { break; } ExtractFolderEntry(folderEntry, destination, ref progressHandler); } }