using System.IO; using System.Text; using Compress.SevenZip.Compress.LZMA; using Compress.SevenZip.Structure; using Compress.Utils; using FileInfo = RVIO.FileInfo; using FileStream = RVIO.FileStream; namespace Compress.SevenZip { public partial class SevenZ { private Stream _lzmaStream; private ulong _packStreamStart; private ulong _packStreamSize; private ulong _unpackedStreamSize; private byte[] _codeMSbytes; public ZipReturn ZipFileCreate(string newFilename) { return ZipFileCreate(newFilename, true); } public ZipReturn ZipFileCreateFromUncompressedSize(string newFilename, ulong unCompressedSize) { return ZipFileCreate(newFilename, true, GetDictionarySizeFromUncompressedSize(unCompressedSize)); } public ZipReturn ZipFileCreate(string newFilename, bool compressOutput, int dictionarySize = 1 << 24, int numFastBytes = 64) { if (ZipOpen != ZipOpenType.Closed) { return ZipReturn.ZipFileAlreadyOpen; } DirUtil.CreateDirForFile(newFilename); _zipFileInfo = new FileInfo(newFilename); int errorCode = FileStream.OpenFileWrite(newFilename, out _zipFs); if (errorCode != 0) { ZipFileClose(); return ZipReturn.ZipErrorOpeningFile; } ZipOpen = ZipOpenType.OpenWrite; _signatureHeader = new SignatureHeader(); _header = new Header(); using (BinaryWriter bw = new BinaryWriter(_zipFs, Encoding.UTF8, true)) { _signatureHeader.Write(bw); } _baseOffset = _zipFs.Position; _compressed = compressOutput; _unpackedStreamSize = 0; if (_compressed) { LzmaEncoderProperties ep = new LzmaEncoderProperties(true, dictionarySize, numFastBytes); LzmaStream lzs = new LzmaStream(ep, false, _zipFs); _codeMSbytes = lzs.Properties; _lzmaStream = lzs; /* ZstandardStream zss = new ZstandardStream(_zipFs, 22, true); _codeMSbytes = new byte[] { 1, 4, 18, 0, 0 }; _lzmaStream = zss; */ _packStreamStart = (ulong)_zipFs.Position; } return ZipReturn.ZipGood; } public void ZipFileAddDirectory(string filename) { string fName = filename; if (fName.Substring(fName.Length - 1, 1) == @"/") fName = fName.Substring(0, fName.Length - 1); LocalFile lf = new LocalFile { FileName = fName, UncompressedSize = 0, IsDirectory = true, StreamOffset = 0 }; _localFiles.Add(lf); } public void ZipFileAddZeroLengthFile() { // do nothing here for 7zip } public ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong uncompressedSize, ushort compressionMethod, uint? datetime, out Stream stream) { return ZipFileOpenWriteStream(filename, uncompressedSize, out stream); } private ZipReturn ZipFileOpenWriteStream(string filename, ulong uncompressedSize, out Stream stream) { LocalFile lf = new LocalFile { FileName = filename, UncompressedSize = uncompressedSize, StreamOffset = (ulong)(_zipFs.Position - _signatureHeader.BaseOffset) }; if (uncompressedSize == 0 && filename.Substring(filename.Length - 1, 1) == "/") { lf.FileName = filename.Substring(0, filename.Length - 1); lf.IsDirectory = true; } _unpackedStreamSize += uncompressedSize; _localFiles.Add(lf); stream = _compressed ? _lzmaStream : _zipFs; return ZipReturn.ZipGood; } public ZipReturn ZipFileCloseWriteStream(byte[] crc32) { _localFiles[_localFiles.Count - 1].CRC = new[] { crc32[3], crc32[2], crc32[1], crc32[0] }; return ZipReturn.ZipGood; } private static readonly int[] DictionarySizes = { 0x10000, 0x18000, 0x20000, 0x30000, 0x40000, 0x60000, 0x80000, 0xc0000, 0x100000, 0x180000, 0x200000, 0x300000, 0x400000, 0x600000, 0x800000, 0xc00000, 0x1000000, 0x1800000, 0x2000000, 0x3000000, 0x4000000, 0x6000000 }; private static int GetDictionarySizeFromUncompressedSize(ulong unCompressedSize) { foreach (int v in DictionarySizes) { if ((ulong)v >= unCompressedSize) return v; } return DictionarySizes[DictionarySizes.Length - 1]; } } }