Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }