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 = header.RawHeader.MainStreamsInfo; streamsInfo.PackInfo = new SevenZipHeader.PackInfo() { NumPackStreams = numPackStreams, PackPos = 0, Sizes = new ulong[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((ulong)1, (int)numStreams).ToArray(), NumUnPackStreamsTotal = numStreams, UnPackSizes = new List <ulong>((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((ulong)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; } }
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 = 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 ulong[1] { numStreams }, NumUnPackStreamsTotal = numStreams, UnPackSizes = new List <ulong>((int)numStreams), Digests = new SevenZipHeader.Digests(numStreams) }; for (ulong i = 0; i < numStreams; ++i) { streamsInfo.SubStreamsInfo.UnPackSizes.Add((ulong)inputStream.Sizes[i]); streamsInfo.SubStreamsInfo.Digests.CRCs[i] = inputStream.CRCs[i]; } }
private void writeHeaders() { // current position is defined as end of packed streams and beginning of header long endOfPackedStreamsPosition = 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 = (ulong)(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 = stream.Position; } // create start header and calculate header crc headerStream.Position = 0; var startHeader = new SevenZipArchive.StartHeader() { NextHeaderOffset = (ulong)(endOfPackedStreamsPosition - Marshal.SizeOf(typeof(SevenZipArchive.SignatureHeader))), NextHeaderSize = (ulong)headerStream.Length, NextHeaderCRC = CRC.Calculate(headerStream) }; // 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 = CRC.Calculate(startHeader.GetByteArray()), StartHeader = startHeader }; // write start header and flush all pending writes stream.Position = 0; stream.Write(signatureHeader.GetByteArray(), 0, Marshal.SizeOf(signatureHeader)); stream.Flush(); }