private async Task ExtractFileAsync(Stream input, ArchivedFile file, string folder, CancellationTokenSource tokenSource, ProgressArgs args) { var root = huffman.BuildTree(file.Codes); using (var output = new FileStream(Path.Combine(folder, file.Name), FileMode.Create, FileAccess.Write, FileShare.None)) { input.Seek(file.Offset, SeekOrigin.Begin); await huffman.DecompressAsync(input, output, file.BitsLength, root, tokenSource, this, args); } }
public async Task CreateAsync(string[] inputFiles, Stream output, CancellationTokenSource tokenSource) { if (inputFiles == null || inputFiles.Length == 0) { throw new ArgumentNullException("inputFile"); } if (output == null) { throw new ArgumentNullException("output"); } await Task.Run(async() => { var args = new ProgressArgs { TotalFiles = inputFiles.Length }; OnReport(args); var token = tokenSource.Token; token.ThrowIfCancellationRequested(); using (var bw = new BinaryWriter(output, new UTF8Encoding(), true)) { var archive = new Archive(); var allCodes = new IEnumerable <SymbolCode> [inputFiles.Length]; var beginPosition = output.Position; bw.Seek(4, SeekOrigin.Current); for (int i = 0; i < inputFiles.Length; i++) { token.ThrowIfCancellationRequested(); var inputFile = inputFiles[i]; using (var input = File.OpenRead(inputFile)) { var codes = huffman.GetCodes(input).ToArray(); allCodes[i] = codes; var originalSize = new FileInfo(inputFile).Length; var file = new ArchivedFile(Path.GetFileName(inputFile), originalSize, 0, 0, codes); bw.Write(file.Name); bw.Write(file.OriginalSize); file.InfoPosition = output.Position; bw.Seek(16, SeekOrigin.Current); var codesPosition = output.Position; bw.Seek(2, SeekOrigin.Current); short codesCount = 0; for (int j = 0; j < codes.Length; j++) { if (codes[j] != null) { bw.Write((byte)j); bw.Write(codes[j].Bits); bw.Write(codes[j].Length); codesCount++; } } var originalPosition = output.Position; output.Position = codesPosition; bw.Write(codesCount); output.Position = originalPosition; archive.Add(file); } } args.TotalSize = archive.OriginalSize; OnReport(args); for (int i = 0; i < inputFiles.Length; i++) { token.ThrowIfCancellationRequested(); args.CurrentFile = i + 1; OnReport(args); var inputFile = inputFiles[i]; using (var input = File.OpenRead(inputFile)) { var codes = allCodes[i]; var file = archive[i]; var offset = output.Position; var bitsLength = await huffman.CompressAsync(input, output, codes, tokenSource, this, args); var compressedPosition = output.Position; var lastArchive = archive.LastOrDefault(); file.BitsLength = bitsLength; file.Offset = offset; output.Position = file.InfoPosition; bw.Write(file.BitsLength); bw.Write(file.Offset); output.Position = compressedPosition; } } var endPosition = output.Position; output.Position = beginPosition; bw.Write(archive.FilesCount); output.Position = endPosition; } }, tokenSource.Token); }