示例#1
0
        private void compressFilesNonSolid(ulong numStreams, Dictionary <ulong, ulong> streamToFileIndex, SevenZipProgressProvider progressProvider)
        {
            var sc = new SevenZipStreamsCompressor(stream);

            sc.Method = Compression.Registry.Method.LZMA;

            // actual compression (into a single packed stream per file)
            SevenZipStreamsCompressor.PackedStream[] css = new SevenZipStreamsCompressor.PackedStream[numStreams];
            ulong numPackStreams = 0;

            for (ulong i = 0; i < numStreams; ++i)
            {
                SevenZipArchiveFile file = _Files[(int)streamToFileIndex[i]];

                Trace.TraceInformation($"Compressing `{file.Name}`, Size: `{file.Size} bytes`...");
                using (Stream source = file.Source.Get(FileAccess.Read))
                    css[i] = sc.Compress(source, progressProvider);

                numPackStreams += css[i].NumStreams;
            }

            // build headers
            var streamsInfo = this.header.RawHeader.MainStreamsInfo;

            streamsInfo.PackInfo = new SevenZipHeader.PackInfo()
            {
                NumPackStreams = numPackStreams,
                PackPos        = 0,
                Sizes          = new UInt64[numPackStreams],
                Digests        = new SevenZipHeader.Digests(numPackStreams)
            };
            streamsInfo.UnPackInfo = new SevenZipHeader.UnPackInfo()
            {
                NumFolders = numStreams,
                Folders    = new SevenZipHeader.Folder[numStreams]
            };

            streamsInfo.SubStreamsInfo = new SevenZipHeader.SubStreamsInfo(streamsInfo.UnPackInfo)
            {
                NumUnPackStreamsInFolders = Enumerable.Repeat((UInt64)1, (int)numStreams).ToArray(),
                NumUnPackStreamsTotal     = numStreams,
                UnPackSizes = new List <UInt64>((int)numStreams),
                Digests     = new SevenZipHeader.Digests(numStreams)
            };

            for (ulong i = 0, k = 0; i < numStreams; ++i)
            {
                for (ulong j = 0; j < css[i].NumStreams; ++j, ++k)
                {
                    streamsInfo.PackInfo.Sizes[k]        = css[i].Sizes[j];
                    streamsInfo.PackInfo.Digests.CRCs[k] = css[i].CRCs[j];
                }
                streamsInfo.SubStreamsInfo.UnPackSizes.Add((UInt64)css[i].Folder.GetUnPackSize());
                streamsInfo.SubStreamsInfo.Digests.CRCs[i] = css[i].Folder.UnPackCRC;
                css[i].Folder.UnPackCRC           = null;
                streamsInfo.UnPackInfo.Folders[i] = css[i].Folder;
            }
        }
示例#2
0
        private void compressFilesSolid(ulong numStreams, Dictionary <ulong, ulong> streamToFileIndex, SevenZipProgressProvider progressProvider)
        {
            var sc = new SevenZipStreamsCompressor(stream);

            sc.Method = Compression.Registry.Method.LZMA;

            Trace.TraceInformation($"Compressing `{numStreams} files` into a solid block...");

            // actual compression using a sequence file stream and stream compressor
            var inputStream = new MultiFileStream(
                FileAccess.Read,
                streamToFileIndex.Select(sfi => _Files[(int)sfi.Value].Source).ToArray());

            SevenZipStreamsCompressor.PackedStream cs = sc.Compress(inputStream, progressProvider);

            // build headers
            var streamsInfo = this.header.RawHeader.MainStreamsInfo;

            streamsInfo.PackInfo = new SevenZipHeader.PackInfo()
            {
                NumPackStreams = cs.NumStreams,
                PackPos        = 0,
                Sizes          = cs.Sizes,
                Digests        = new SevenZipHeader.Digests(cs.NumStreams)
                {
                    CRCs = cs.CRCs
                }
            };
            streamsInfo.UnPackInfo = new SevenZipHeader.UnPackInfo()
            {
                NumFolders = 1,
                Folders    = new SevenZipHeader.Folder[1]
                {
                    cs.Folder
                }
            };
            streamsInfo.UnPackInfo.Folders[0].UnPackCRC = null;
            streamsInfo.SubStreamsInfo = new SevenZipHeader.SubStreamsInfo(streamsInfo.UnPackInfo)
            {
                NumUnPackStreamsInFolders = new UInt64[1]
                {
                    numStreams
                },
                NumUnPackStreamsTotal = numStreams,
                UnPackSizes           = new List <UInt64>((int)numStreams),
                Digests = new SevenZipHeader.Digests(numStreams)
            };
            for (ulong i = 0; i < numStreams; ++i)
            {
                streamsInfo.SubStreamsInfo.UnPackSizes.Add((UInt64)inputStream.Sizes[i]);
                streamsInfo.SubStreamsInfo.Digests.CRCs[i] = inputStream.CRCs[i];
            }
        }
示例#3
0
        private void writeHeaders()
        {
            // current position is defined as end of packed streams and beginning of header
            long endOfPackedStreamsPosition = this.stream.Position;

            // write headers in temporary stream
            var headerStream = new MemoryStream();

            header.Write(headerStream);

            // go through compressing again for headers
            if (CompressHeader)
            {
                // get compressor and default codec
                var sc = new SevenZipStreamsCompressor(stream);
                sc.Method = Compression.Registry.Method.LZMA;

                // compress
                headerStream.Position = 0;
                SevenZipStreamsCompressor.PackedStream cs = sc.Compress(headerStream, null);

                // create encoded header
                SevenZipHeader.StreamsInfo headerStreamsInfo = new SevenZipHeader.StreamsInfo()
                {
                    PackInfo = new SevenZipHeader.PackInfo()
                    {
                        NumPackStreams = cs.NumStreams,
                        PackPos        = (UInt64)(endOfPackedStreamsPosition - Marshal.SizeOf(typeof(SevenZipArchive.SignatureHeader))),
                        Sizes          = cs.Sizes,
                        Digests        = new SevenZipHeader.Digests(1)
                        {
                            CRCs = cs.CRCs
                        }
                    },
                    UnPackInfo = new SevenZipHeader.UnPackInfo()
                    {
                        Folders = new SevenZipHeader.Folder[1] {
                            cs.Folder
                        },
                        NumFolders = 1
                    }
                };

                // bait and switch
                header.RawHeader     = null;
                header.EncodedHeader = headerStreamsInfo;

                // write new header in headerStream
                headerStream.Dispose();
                headerStream = new MemoryStream();
                header.Write(headerStream);

                // update new end of packed position for encoded header
                endOfPackedStreamsPosition = this.stream.Position;
            }

            // create start header and calculate header crc
            headerStream.Position = 0;
            var startHeader = new SevenZipArchive.StartHeader()
            {
                NextHeaderOffset = (UInt64)(endOfPackedStreamsPosition - Marshal.SizeOf(typeof(SevenZipArchive.SignatureHeader))),
                NextHeaderSize   = (UInt64)headerStream.Length,
                NextHeaderCRC    = new CRC().Calculate(headerStream).Result
            };

            // write headers at the end of output stream
            headerStream.Position = 0;
            headerStream.CopyTo(stream);
            headerStream.Dispose();

            // regenerate signature header with positions and crcs
            var signatureHeader = new SevenZipArchive.SignatureHeader()
            {
                Signature      = SevenZipArchive.kSignature.ToArray(),
                ArchiveVersion = new SevenZipArchive.ArchiveVersion()
                {
                    Major = 0,
                    Minor = 2,
                },
                StartHeaderCRC = new CRC().Calculate(startHeader.GetByteArray()).Result,
                StartHeader    = startHeader
            };

            // write start header and flush all pending writes
            stream.Position = 0;
            stream.Write(signatureHeader.GetByteArray(), 0, Marshal.SizeOf(signatureHeader));
            stream.Flush();
        }